SQLite 允许在存储在数据库中的字符串值的中间使用空字符(ASCII 0x00,Unicode \u0000)。但是,在字符串中使用空字符会导致意外的行为
The length() SQL 函数 仅计算到第一个空字符(不含)之前的字符。
The quote() SQL 函数 仅显示到第一个空字符(不含)之前的字符。
The .dump 命令在 CLI 中会省略第一个空字符以及它生成的 SQL 输出中所有后续文本。实际上,CLI 会在所有上下文中省略第一个空字符之后的任何内容。
不建议在 SQL 文本字符串中使用空字符。
考虑以下 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 的工作方式。
如果将字符串 CAST 为 BLOB,则会显示字符串的整个长度。例如
SELECT a, CAST(b AS BLOB) FROM t1;
给出以下结果
1,X'6162630078797a'
在 BLOB 输出中,你可以清楚地看到空字符是 7 个字符字符串中的第 4 个字符。
另一种更自动化的判断字符串值 X 是否包含嵌入空字符的方法是使用以下表达式
instr(X,char(0))
如果此表达式返回非零值 N,则在第 N 个字符位置存在一个嵌入的空字符。因此,要统计包含嵌入空字符的行数
SELECT count(*) FROM t1 WHERE instr(b,char(0))>0;
以下示例显示了如何从表的列中删除空字符,以及所有后续文本。因此,如果你有一个包含嵌入空字符的数据库文件,并且你想将其删除,则运行类似于以下内容的 UPDATE 语句可能会有所帮助
UPDATE t1 SET b=substr(b,1,instr(b,char(0))) WHERE instr(b,char(0));
此页面上次修改于 2022-05-23 22:21:54 UTC