プログラミング
SQLiteにおける文字列中のNUL文字
Nul Characters in Strings in SQLite (sqlite.org)
要約
SQLiteでは、データベースに格納される文字列値の中間にNUL文字(ASCII 0x00)を許可していますが、これが予期せぬ動作を引き起こす可能性があります。length()関数やquote()関数は最初のNUL文字までしか処理せず、CLIの.dumpコマンドもNUL文字以降を省略します。NUL文字の混入は推奨されません。
全文翻訳
小さく。速く。信頼できる。そのどれでも選んでください。
ホーム メニュー ドキュメント ダウンロード ライセンス サポート 購入 検索
ドキュメント 検索
変更履歴
文字列中のNUL文字
1. はじめに
SQLiteは、データベースに格納される文字列値の中間にNUL文字(ASCII 0x00、Unicode \u0000)を許可します。しかし、文字列内でのNULの使用は、驚くべき動作につながる可能性があります。
length() SQL関数は、最初のNUL文字まで、およびそれより前の文字のみをカウントします。
quote() SQL関数は、最初のNUL文字まで、およびそれより前の文字のみを表示します。
CLIの.dumpコマンドは、生成されるSQL出力において、最初のNUL文字とその後のすべてのテキストを省略します。事実上、CLIはすべてのコンテキストで最初のNUL文字以降のすべてを省略します。
SQLテキスト文字列でのNUL文字の使用は推奨されません。
2. 予期せぬ動作
以下のSQLを検討してください。
CREATE TABLE t1( a INTEGER PRIMARY KEY, b TEXT );
INSERT INTO t1(a,b) VALUES(1, 'abc'||char(0)||'xyz');
SELECT a, b, length(b) FROM t1;
上記のSELECT文は、以下の出力を示します。
1,'abc',3
(このドキュメントでは、CLIで".mode quote"が設定されていると仮定します。)
しかし、以下を実行するとどうなるでしょうか。
SELECT * FROM t1 WHERE b='abc';
すると、行は返されません。SQLiteは、t1.bカラムが実際には7文字の文字列を保持しており、7文字の文字列 'abc'||char(0)||'xyz' は3文字の文字列 'abc' と等しくないことを認識しているため、行は返されません。しかし、CLIの出力が文字列を3文字としか示さないため、ユーザーは容易に混乱する可能性があります。これはバグのように見えます。しかし、これがSQLiteの動作方法です。
3. 文字列にNUL文字が含まれているかどうかを確認する方法
文字列をBLOBにCASTすると、文字列全体の長さが表示されます。例えば:
SELECT a, CAST(b AS BLOB) FROM t1;
この結果が得られます。
1,X'6162630078797a'
BLOB出力では、7文字の文字列の4番目の文字としてNUL文字をはっきりと見ることができます。
文字列値Xに埋め込まれたNUL文字が含まれているかどうかを判断する、より自動化された方法は、次のような式を使用することです。
instr(X,char(0))
この式がゼロ以外の値Nを返す場合、N番目の文字位置に埋め込まれたNULが存在します。したがって、埋め込まれたNUL文字を含む行数をカウントするには:
SELECT count(*) FROM t1 WHERE instr(b,char(0))>0;
4. テキストフィールドからNUL文字を削除する
以下の例は、テーブルのカラムからNUL文字とその後のすべてのテキストを削除する方法を示しています。したがって、埋め込まれたNULを含むデータベースファイルがあり、それらを削除したい場合は、次のようなUPDATEステートメントを実行すると役立つかもしれません。
UPDATE t1 SET b=substr(b,1,instr(b,char(0))) WHERE instr(b,char(0));
このページは2022-05-23 22:21:54Zに最後に更新されました。