Small. Fast. Reliable.
Choose any three.
字符串中的NUL字符

1.简介

SQLite允许在数据库中存储的字符串值中间使用NUL字符(ASCII 0x00,Unicode \ u0000)。但是,在字符串中使用NUL可能会导致令人惊讶的行为:

  1. 长度()SQL函数只计算字符,直到通过与除第一NUL。

  2. 报价()SQL函数只能显示字符,直到通过和排除第一NUL。

  3. CLI中.dump命令忽略了它生成的SQL输出中的第一个NUL字符和所有后续文本。实际上, CLI在所有情况下都忽略了第一个NUL字符之后的所有内容。

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

2.意外行为

考虑以下SQL:

创建表t1(
  整数主键,
  b文字
);
插入t1(a,b)VALUES(1,'abc'|| char(0)||'xyz');

从t1中选择a,b,length(b);

上面的SELECT语句显示以下内容的输出:

1,'abc',3

(通过本文档,我们假定CLI设置了“ .mode quote ”。)但是,如果运行:

选择*从t1哪里b ='abc';

然后,不返回任何行。SQLite知道t1.b列实际上包含7个字符的字符串,并且7个字符的字符串'abc'|| char(0)||'xyz'不等于3个字符的字符串'abc',并且因此不返回任何行。但是用户可能会对此感到困惑,因为CLI输出似乎显示该字符串只有3个字符。这似乎是一个错误。但这是SQLite的工作方式。

3.如何判断字符串中是否包含NUL字符

如果将字符串CAST投射到BLOB中,则会显示字符串的整个长度。例如:

从t1选择a,CAST(b AS BLOB);

给出以下结果:

1,X'6162630078797a'

在BLOB输出中,您可以清楚地看到NUL字符作为7个字符的字符串中的第4个字符。

判断字符串值X是否包含嵌入式NUL字符的另一种更自动化的方法是使用类似以下的表达式:

instr(X,char(0))

如果此表达式返回非零值N,则在第N个字符位置存在一个嵌入式NUL。因此,要计算包含嵌入式NUL字符的行数:

从t1处选择count(*)instr(b,char(0))> 0;

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

下面的示例说明如何从表的列中删除NUL字符以及其后的所有文本。因此,如果您有一个包含嵌入式NUL的数据库文件,并且想要删除它们,那么运行类似于以下内容的UPDATE语句可能会有所帮助:

更新t1设置b = substr(b,1,instr(b,char(0)))
 在哪里instr(b,char(0));