記事公開日
最終更新日
SQLデータベースの話(その1)WindowsのSQLite3で正しく日本語を扱う

(本記事の情報は、記事の公開日時点での情報であり、その正確性、完全性、最新性等内容を保証するものではありません。)
SQLiteはオープンソースのライブラリー型データベースで、アプリケーションのメモリ中で非常に高速に動作します。
OracleやSQL Serverの何倍も高速です。
SQL構文もかなり標準対応が高度で、使用した限りクエリ結果も正確です。サーバー型ではないので、同時に一人だけしか使えませんが、複雑なデータ加工を、SQLエンジンを使用して操作するのには非常に適しています。
SQLite公式サイトはこちら
C言語等でアプリケーションを作成するなら、APIを用いてライブラリをリンクするのですが、作成したデータベースを汎用の検索エンジンで使用したり、アプリケーションを他のRDBMSでも動作するように作りたいなら、ODBC汎用にして開発するのが良いでしょう。
ただし、SQLite3はシフトJISに対応していないため、通常のODBCアプリケーションのルールでは文字化けしてしまいます。
オープンソースなので、シフトJIS対応したODBCドライバーも有志が提供しているようですが、今回ご紹介する方法で標準のまま対応可能です。
ODBCはデータ獲得のためにAPIで1カラムずつ取得する方法と、バインドバッファというメモリー領域に一度に取得する方法があります。
APIの場合、Unicodeアプリケーションならば、文字コードはワイド文字(Unicode)固定になり、SQLite3でも文字化けしません。
しかし、バインドバッファ経由では問題があります。
ODBCにはバインドバッファ上の文字コードを指定するAPIがありませんが、文字型をローカルコード(SQL_C_CHAR:日本語WindowsだとシフトJIS)かワイド文字(SQL_C_WCHAR:Unicode)に指定することはできます。
日本語WindowsではSQL_C_CHARで指定したときの文字コードはローカルコードつまりシフトJISがルールですが、SQLite3の場合はUTF-8になってしまいます。おそらく物理格納されているデータをそのまま返しているのでしょう。
文字コードをローカルコードでなくUTF8で扱えるツールはまず無いので、正しく日本語が扱えないわけです。
SQLite3で正しく日本語を扱うには以下のようにします。
- データベースファイル生成時に、encodingをutf-8にする
これはデフォルトなので特に変更しなければ問題は無いです。 - CHAR系のバインドバッファの型をSQL_C_WCHARに指定する
アプリの場合はSQLBindColの第3パラメータあるいはSQLBindParameterの第4パラメータをSQL_C_WCHARにすれば、バインドバッファにUnicodeでデータが格納されます。
ツールの場合は、Create Table時のデータ型をCHAR(VARCHAR)からNCHAR(NVARCHAR)に変更します。こうすればツールがSQLDescribeColやSQLDescribeParamで獲得するカラム型がSQL_WCHARになるので、対応しているツールならバインドバッファの型もSQL_C_WCHARに設定されるはずです。
注意するのは、ODBC設定で「NO WCHAR」チェックをオンにしないことです。これはデフォルトがオフなので、自分で変更しない限り問題にはなりません。

データ加工シーンでは文字化けの危険を避けるため、入力データと同じ文字コードでデータベースを構築し、ODBC等のインターフェースでコード変換をさせないように配慮するのですが、Windowsでは基本的にUnicode-シフトJIS間の文字コードは相互変換が保証されているので、Windowsで使用する限りは文字化けの危険は無いと思います。
しかし、データの提供元がメインフレームやUNIXなどWindowsでない場合には、アプリケーションで投入するデータがWindowsで許されるコード範囲内にあるかどうかチェックする等の対応が必要でしょう
関連コンテンツ
SQLデータベースの話(その2)ODBCドライバと各社RDBクライアント文字コードの関係