小巧。快速。可靠。
三者选其二。
字符串中的空字符

1. 简介

SQLite 允许在存储在数据库中的字符串值的中间使用空字符(ASCII 0x00,Unicode \u0000)。但是,在字符串中使用空字符会导致意外的行为

  1. The length() SQL 函数 仅计算到第一个空字符(不含)之前的字符。

  2. The quote() SQL 函数 仅显示到第一个空字符(不含)之前的字符。

  3. The .dump 命令在 CLI 中会省略第一个空字符以及它生成的 SQL 输出中所有后续文本。实际上,CLI 会在所有上下文中省略第一个空字符之后的任何内容。

不建议在 SQL 文本字符串中使用空字符。

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. 如何判断字符串中是否包含空字符

如果将字符串 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;

4. 从文本字段中删除空字符

以下示例显示了如何从表的列中删除空字符,以及所有后续文本。因此,如果你有一个包含嵌入空字符的数据库文件,并且你想将其删除,则运行类似于以下内容的 UPDATE 语句可能会有所帮助

UPDATE t1 SET b=substr(b,1,instr(b,char(0)))
 WHERE instr(b,char(0));

此页面上次修改于 2022-05-23 22:21:54 UTC