在SQLite中,WHERE - IS NULL无法正常工作?

36

有一个奇怪的问题:

我可以从SQLite中过滤出非空的内容,但无法过滤出的内容:

这个可以正常工作:

SELECT * FROM project WHERE parent_id NOT NULL;

这些不行:

SELECT * FROM project WHERE parent_id IS NULL; 
SELECT * FROM project WHERE parent_id ISNULL; 
SELECT * FROM project WHERE parent_id NULL;

所有返回值:

您的查询语法存在问题(查询未执行)...

更新:

我正在使用PHP通过ezSQl代码,并使用PHPLiteAdmin界面进行操作。

PHPLiteAdmin演示版中,此表达式有效- 所以现在我怀疑我的PHP的SQLite版本是否有问题?是这样吗?这个表达式一直都有效吗?

更新2:

当我使用ezSQL从PHP运行代码时,PHP警告如下:

PHP警告:SQL逻辑错误或缺失数据库

有没有办法从PHP中获取更多信息?这太让人恼火、难以理解了,尤其是因为CLI中相同的语句可以正常工作...

更新3:

我唯一可能的线索是:我用PHP创建的数据库无法被CLI读取,反之亦然。我会得到:

错误:文件已加密或不是数据库

所以这里肯定有两种SQlite版本发生了冲突。(查看此处) 但是,为什么语句无效呢?

更新4:

好吧,我认为我已经找到了罪魁祸首,虽然不知道原因- 我使用PHP ezSQL创建的DB是“IS NULL”语句无法运行的数据库。如果我使用PHP的SQLite3类创建数据库,则该语句可以正常工作,而且我还可以从CLI访问该数据库,而ezSQL创建的数据库则会出现“文件已加密”的错误。

所以,我稍微研究了一下ezSQL代码- 发现它使用PDO方法而不是较新的SQLite3类。也许这就是问题所在- 我不想再浪费时间了...

无论如何,我已经找到了解决方案,那就是避免使用ezSQL,直接使用PHP的SQLite3类。


5
您的第一个IS NULL语法是正确的。在这种情况下,您需要告诉我们如何将该命令发送到SQLite。该错误消息似乎不是来自sqlite3命令行界面。 - Larry Lustig
通过PHP和phpliteadmin http://www.danedesigns.com/phpliteadmin.php,以及在我的PHP代码中使用ezsql,来操作Larry。 - Yarin
1
我的猜测是PHPLiteAdmin误报了其他问题。可能是缺少或位置错误的数据库文件,或者其他任何问题。 - Larry Lustig
不,我是使用PHPLiteAdmin来检查为什么我的代码出错。在PHP中,警告是“PHP Warning: SQL逻辑错误或缺少数据库”-再次强调,数据库、表和数据都在那里-当NOT被包含时,确切的语句可以正常工作...我知道听起来很奇怪,但事实就是这样。 - Yarin
好的,那么这是一个坏的或缺失的数据库文件。可能性是(严重的)不同版本的 SQLite 或更有可能的是,你没有指示你的 SQL 库打开你认为正在打开的文件。 - Larry Lustig
1
如果您将您的解决方案添加为答案并接受它,那将会非常有用。并不是每个人都会读完您的问题直到“更新4”。 - user2443147
6个回答

47

a IS ba IS NOT b 是一般形式,其中 ab 是表达式。

这通常只出现在 a IS NULLa IS NOT NULL 的情况下。还有 ISNULLNOTNULL(也是 NOT NULL)运算符,它们分别是前面表达式的简写(它们只接受一个操作数)。

SQLite 表达式中理解的 SQL 内容在 SQLite Query Language: Expressions 中介绍。

如果使用 CLI,请确保先用 ; 终止(之前的)语句。

这些都是否定“空匹配”的有效方法:

expr NOT NULL
expr NOTNULL
expr IS NOT NULL

以下都是“匹配 null”的有效方式:

expr ISNULL
expr IS NULL

由于上述所有结构本身都是表达式,所以否定也是有效的(例如,NOT (expr NOT NULL) 等同于 expr IS NULL)。

祝编码愉快。


实践出真知:

SQLite version 3.7.7.1 2011-06-28 17:39:05
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> create table x (y int null);
sqlite> select * from x where y isnull;
sqlite> select * from x where y notnull;
sqlite> select * from x where y not null;
sqlite> select * from x where y is null;
sqlite> select * from x where y is not null;
sqlite>

1
@pst- 我很感谢你的回答,但 IS NULL 不起作用。我的语句已经被正确分隔,因为 IS NOT NULL 表达式可以正常工作。我知道文档上说什么,但这就是我得到的结果... - Yarin
@pst- 如果有帮助的话,我是通过PHP ezsql运行这些内容的。 - Yarin
从CLI运行你的测试很好...奇怪。 - Yarin
@Yarin SQLite所理解的语法(对于给定版本)不会改变(CLI只是一个原始交互层)。也许有些东西试图“重新解释”查询? - user166390
希望你能解决它(并发布解决方案/原因)。我在SO上的“成功”定义是不会被踩票;-) - user166390
显示剩余5条评论

8
问题可能源于SQLite如何处理空列。例如,仅仅因为一列为空并不意味着它是NULL。你是否测试过对 "" 的情况?
SELECT * FROM project WHERE parent_id = ""

那个查询可能会返回结果。


parent_id = "" 和 parent_id <> "" 总是有效的。 - Reign.85

7
在 Android SQLite 中,field IS NULL 也不起作用。但是使用 field = 'null' 可以解决问题。请在您的环境中尝试一下。

奇怪...我刚发现在某些情况下 字段为空 是有效的。 - Jose_GD
1
在我的情况下,列类型是INTEGER。Android API15模拟器中column_name=0可以工作。Android API15手机中column_name ISNULL(和IS NULL)可以工作。希望这能帮助其他人。 - IT-Dan

2

这个在Firefox的SQLite Manager中适用于SQLite:

          select * from foo where not baz is not null

上面的查询返回列 [baz] 为 null 的行。:-) Yarin,也许这对你有用? (在列名前的 'not' 不是笔误)。

这个查询也会找到 baz 为空的行:

         select * from foo where [baz]  is  null

你正在尝试测试空值的列的确切数据类型是什么(按照CREATE TABLE语句中声明的方式)? - Tim

0

如果您正在测试主键列,而该列被视为rowid的同义词,则没有行的rowid将为null。


-2

尝试使用 where your_col_name ISNULL,其中 ISNULL 不包含空格


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接