大西彰のウェブログ

データベース系技術ネタ、国際化技術ネタなど、徒然なるままに

目次

Blog 利用状況

ニュース


こんにちは。大西 彰です。
私のブログでは、データベース技術、ソフトウェアの国際化などを取り扱っています。ニッチだけど重要なネタがつまっています。
ブログの内容は無保証です。
また、本ブログでの発言やコメントは、マイクロソフトの正式な見解またはコメントではありません。



マイクロソフトライセンスセンター
マイクロソフトライセンスセンター
マイクロソフトライセンスセンター
ウィルコムストア
ソースネクスト
デル株式会社
アフィリエイト リンクシェア ブログ 携帯対応 成果報酬 広告 テンプレート ブログパーツ

テクノラティプロフィール

記事のカテゴリ

過去の記事

カテゴリ

イメージギャラリ

My blog

Visual FoxPro

Visual Studio

Web Sites

Windows Vista

ブログ

免責事項

UTF-8対応Webアプリケーションの構築: 第3回(VB6.0)

UTF-8対応Webアプリケーションの構築: 第3回(VB6.0)
UTF-8対応Webアプリケーションの構築の記事の第3回は、Visual Basic 6.0(以下、VB6)を取り上げたいと思います。
本題に入る前に、前回までのおさらいをしてみましょう。
アプリケーションの全体像は次のようになります。

+-----------+   +--------------+   +---------------+
|Webブラウザ|←ⅰ→|Webサーバ(IIS)|←ⅱ→|ASP プログラム|
+-----------+   +--------------+   +---------------+
                      ↑
                      ⅲ
                      ↓
                     +-----------+
                     |ActiveX DLL|
                     +-----------+
                      ↑
                      ⅳ
                      ↓
                     +-----+   +--------+
                     |ADODB|←ⅴ→|MSDE2000|
                     +-----+   +--------+

一見ややこしい感じを受けますが、Webブラウザから送出されたUTF-8文字列が無事にMSDEに格納され、反対にMSDEに格納されているUCS-2文字列がWebブラウザに対してUTF-8で返されることが要求されます。上記の図において、第1回はASPの話、第2回はMSDEの話を通じて
・ⅰ、ⅱがUTF-8での通信(ⅱですでにUCS-2になっているかもしれないけど)
・ⅲは、UCS-2の文字列
・MSDEに格納できるのは、クエリ前提ならばUCS-2
であることを説明しました。
今回の記事では、残る通信経路であるⅳとⅴを見ていきましょう。ⅲがUCS-2である以上、ⅳとⅴはUCS-2での通信にならなければ困ります。ではどうすればいいのでしょうか。

あまり意識されることがないかと思いますが、VB6の世界において、内部の文字コードはUnicodeです。ここでいうUnicodeはWindowsのUnicodeですのでUCS-2です。シフトJISのようなMBCSでないということです。

この仕様が今回のようなUnicode対応アプリケーションを構築する上で大変便利です。つまり、経路ⅲとⅳにおいて、文字列はUCS-2のUnicodeだということです。Unicodeであるので、事実上、OSの言語には依存せず、VB6の英語版でも日本語版でも文字列操作は内部的にはUCS-2で実行されます。私の経験においては、VB6の英語版でActiveX DLLを作る必要があったので、MBCSとUnicodeの変換から解放されるのはとても喜ばしいことでした。

さて、残るは、経路ⅴです。ここまでくると、ADODBとMSDEの間は、やはりUCS-2でなければ困ります。ここからは、ADODBの使いこなしひとつで勝負が決まります。ADODBでSQL文を実行するには、いくつかの方法があります。対Unicodeをきちんと意識するために、ADODB.Commandを利用することを前提に話を進めましょう。
ADODB.Commandオブジェクトを使って、SQL文を呼び出す場合、Parametersコレクションを使って、SQL文に渡すパラメータについて細かく指定することができます。Parameters.Appendメソッドを利用することで、各パラメータを定義できます。ここで重要になるのは、Unicodeに対応したデータ型を指定するということです。もっと厳密に言えば、DataTypeEnum値を指定するということです。

DataTypeEnum値において、Unicodeを指定する場合は、次のような定数があります。

・adWChar     : MSDE(SQL Server)のncharに対応
・adVarWChar   : MSDE(SQL Server)のnvarcharに対応
・adLongVarWChar : MSDE(SQL Server)のntextに対応

この関係が理解できてしまえば、後は、ADODBを素直に呼び出せばいいのです。
では、第2回で作成したストアドプロシージャを呼び出すクラスを作ってみましょう。
ここからは長くなりますが、VB6のコードを追いかけてください。


' clsUtext.cls
' author: Akira Onishi / copyright(c) 2004, Akira Onishi
Option Explicit
'--------------------------------------------------------------------
' キーワードで検索し、一致したレコードセットを返す
' connString: ADODBの接続文字列
' Keyword: 検索用キーワード
'--------------------------------------------------------------------
Public Function UtextInfo(ByVal connString, ByVal Keyword)
On Error GoTo ErrorHandler:
    Dim oConn As New ADODB.Connection
    Dim CmdP As New ADODB.Command
    Dim rsP  As New ADODB.Recordset

    oConn.Open connString
    rsP.CursorLocation = adUseClient
    With CmdP
        .ActiveConnection = oConn
        .CommandText = "spUtextInfo"
        .CommandType = adCmdStoredProc
        .Parameters.Append .CreateParameter("@Keyword", adVarWChar, _
               adParamInput, 30, Keyword)
    End With
   
    rsP.Open CmdP
    Set rsP.ActiveConnection = Nothing ' オフラインのRecordset作成
    Set UtextInfo = rsP
    oConn.Close
    Set rsP = Nothing
    Set CmdP = Nothing
    Set oConn = Nothing
    Exit Function
ErrorHandler:
    Set rsP = Nothing
    Set CmdP = Nothing
    Set oConn = Nothing
    Set UtextInfo = Nothing
    Err.Raise Err.Number, Err.Source, Err.Description
End Function

'--------------------------------------------------------------------
' すべての行をレコードセットとして返す
' connString: ADODBの接続文字列
'--------------------------------------------------------------------
Public Function UtextAll(ByVal connString)
On Error GoTo ErrorHandler:
    Dim oConn As New ADODB.Connection
    Dim CmdP As New ADODB.Command
    Dim rsP  As New ADODB.Recordset

    oConn.Open connString
    rsP.CursorLocation = adUseClient
    With CmdP
        .ActiveConnection = oConn
        .CommandText = "spUtextAll"
        .CommandType = adCmdStoredProc
    End With
    rsP.Open CmdP
    Set rsP.ActiveConnection = Nothing ' オフラインのRecordset作成
    Set UtextAll = rsP
    oConn.Close
    Set rsP = Nothing
    Set CmdP = Nothing
    Set oConn = Nothing
    Exit Function
ErrorHandler:
    Set rsP = Nothing
    Set CmdP = Nothing
    Set oConn = Nothing
    Set UtextAll = Nothing
    Err.Raise Err.Number, Err.Source, Err.Description
End Function

'--------------------------------------------------------------------
' 行を作成する
' connString: ADODBの接続文字列
' Keyword:キーワードの文字列
' note: メモ用の長い文字列
' ErrMessage: エラーメッセージ格納用文字列
'--------------------------------------------------------------------
Public Function UtextInsert(ByVal connString, ByVal Keyword, _
                                ByVal note, ByRef ErrMessage)
On Error GoTo ErrorHandler:
    Dim oConn As New ADODB.Connection
    Dim cmdUtext As New ADODB.Command
    Dim lTrans As Long

    oConn.Open connString
    lTrans = oConn.BeginTrans
    With cmdUtext
        .ActiveConnection = oConn
        .CommandText = "spUtextInsert"
        .CommandType = adCmdStoredProc
        .Parameters.Append .CreateParameter("@Keyword", adVarWChar, _
                                            adParamInput, 30, Keyword)
        .Parameters.Append .CreateParameter("@note", adLongVarWChar,_
                                             adParamInput, 4000, note)
        .Execute
    End With
    If Err.Number <> 0 Then GoTo ErrorHandler:
    ' トランザクションのコミットと後処理
    oConn.CommitTrans
    oConn.Close
    Set cmdUtext = Nothing
    Set oConn = Nothing
    ErrMessage = "OK"
    Exit Function
ErrorHandler:
    ' ロールバックとエラーの通知
    If lTrans <> 0 Then oConn.RollbackTrans
    Set cmdUtext = Nothing
    Set oConn = Nothing
    ErrMessage = Err.Description
    Err.Raise Err.Number, Err.Source, Err.Description
End Function
'--------------------------------------------------------------------
' 行を更新する
' connString: ADODBの接続文字列
' Keyword:キーワードの文字列
' note: メモ用の長い文字列
' ErrMessage: エラーメッセージ格納用文字列
'--------------------------------------------------------------------
Public Function UtextUpdate(ByVal connString, ByVal Keyword, ByVal note, _
                                                      ByRef ErrMessage)
On Error GoTo ErrorHandler:
    Dim oConn As New ADODB.Connection
    Dim cmdUtext As New ADODB.Command
    Dim lTrans As Long
    Dim ChangePassword As Boolean
    Dim rsinfo As New ADODB.Recordset
   
    oConn.Open connString
    lTrans = oConn.BeginTrans
    With cmdUtext
        .ActiveConnection = oConn
        .CommandText = "spUtextUpdate"
        .CommandType = adCmdStoredProc
        .Parameters.Append .CreateParameter("@Keyword", adVarWChar, _
                                             adParamInput, 30, Keyword)
        .Parameters.Append .CreateParameter("@note", adLongVarWChar, _
                                              adParamInput, 4000, note)
        .Execute
    End With
    If Err.Number <> 0 Then GoTo ErrorHandler:
    ' トランザクションのコミットと後処理
    oConn.CommitTrans
    oConn.Close
    Set cmdUtext = Nothing
    Set oConn = Nothing
    ErrMessage = "OK"
    Exit Function
ErrorHandler:
    ' ロールバックとエラーの通知
    If lTrans <> 0 Then oConn.RollbackTrans
    Set cmdUtext = Nothing
    Set oConn = Nothing
    ErrMessage = Err.Description
    Err.Raise Err.Number, Err.Source, Err.Description
End Function
'--------------------------------------------------------------------
' 行を削除する
' connString: ADODBの接続文字列
' Keyword:キーワードの文字列
' note: メモ用の長い文字列
' ErrMessage: エラーメッセージ格納用文字列
'--------------------------------------------------------------------
Public Function UtextDelete(ByVal connString, ByVal Keyword, _
                                                     ByRef ErrMessage)
On Error GoTo ErrorHandler:
    Dim oConn As New ADODB.Connection
    Dim strSQL As String
    Dim lTrans As Long

    ' ※文字列リテラルでUnicodeを指定する際は、Nプレフィックスが必要!!
    strSQL = "spUtextDelete  " & "N'" & Trim(Keyword) & "'"
    oConn.Open connString
    lTrans = oConn.BeginTrans
    oConn.Execute strSQL
    If Err.Number <> 0 Then GoTo ErrorHandler:
    ' トランザクションのコミットと後処理
    oConn.CommitTrans
    oConn.Close
    Set oConn = Nothing
    ErrMessage = "OK"
    Exit Function
ErrorHandler:
    ' ロールバックとエラーの通知
    If lTrans <> 0 Then oConn.RollbackTrans
    Set oConn = Nothing
    ErrMessage = Err.Description
    Err.Raise Err.Number, Err.Source, Err.Description
End Function

これで、アプリケーションの構成要素間のUnicode問題は解決しました。最後にこれらをまとめれば完成です。長くなりましたので、続きは次回に。

投稿日時 : 2004年9月22日 16:26

コメントを追加

# re: UTF-8対応Webアプリケーションの構築: 第3回(VB6.0) 2005/10/07 15:57 中村剛

この記事助かりました。
' ※文字列リテラルでUnicodeを指定する際は、Nプレフィックスが必要!!
っていうのがわからずにかなり長い間悩んでました。
ありがとうございました!!!!

# re: UTF-8対応Webアプリケーションの構築: 第3回(VB6.0) 2005/10/07 16:11 大西 彰

中村さん、お役に立てたようで何よりです。

SQL ServerやMSDEでUnicodeを扱っていないと気がつかないことですが、NプレフィックスがないとUnicodeとして受け付けてくれなくて、文字化けで悩まされます。一度知ってしまえば単純なことなんですけど、知らないと試行錯誤で苦しみます。かく言う私も苦しんだ一人(^^;

# re: UTF-8対応Webアプリケーションの構築: 第3回(VB6.0) 2007/11/22 18:11 p-nix

2年も前のエントリにコメントしまして大変申し訳ございません。このページを参考にプログラム書いていたのですが、ストアドプロシージャーに名前つきパラメータを渡す際には、
cmdUtext.NamedParameters = True
としないとパラメータ名が無視されて単に上からセットされていく。つまり万が一パラメータ名を間違っていてもそのまま動くので気づかなかったりする恐れは無いでしょうか?自分の場合SQL Server 2005なのですがそのような現象に遭遇したので。
http://msdn.microsoft.com/library/ja/default.asp?url=/library/ja/jpado260/htm/mdpronamedparameters.asp

NamedParametersプロパティに関して検索したのですがほとんど情報がなく、確信が持てないのですがもしご存知であれば。本題のUTF-8とはずれてしまい申し訳ございません。

タイトル  
名前  
URL
コメント