小巧、快速、可靠。
選擇任三項。
字串中的 NUL 字元

1. 簡介

SQLite 允許在資料庫中儲存的字串值中間有 NUL 字元 (ASCII 0x00,Unicode \u0000)。但是,在字串中使用 NUL 可能會導致令人驚訝的行為

  1. length() SQL 函數 僅計算到第一個 NUL 為止(不含第一個 NUL)的字元。

  2. quote() SQL 函數 僅顯示到第一個 NUL 為止(不含第一個 NUL)的字元。

  3. .dump CLI 中的命令會省略第一個 NUL 字元和它在產生的 SQL 輸出中後面的所有文字。事實上,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 字元

如果將字串 CAST 為 BLOB,則會顯示字串的整個長度。例如

SELECT a, CAST(b AS BLOB) FROM t1;

會產生這個結果

1,X'6162630078797a'

在 BLOB 輸出中,你可以清楚地看到 NUL 字元為 7 個字元字串中的第 4 個字元。

另一種更自動化的方式來判斷字串值 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:54 UTC