一、简介
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 字符
如果将字符串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));