最近,我们在生成SQLite查询时遇到了一个问题,我们意外地使用了按位OR:

SELECT * FROM demo WHERE ((nullableId IS NULL) | (nullableId = -1))


我们使用OR运算符解决了此问题。

但是上面的查询有一些我不理解的意外行为:


为什么这甚至有效? (例如,在Microsoft SQL Server中,这显然是语法错误)
为什么结果所有带有nullableId = -1的行?
简而言之,这是怎么回事?

最佳答案

nullableId IS NULL时,条件评估:
nullableId IS NULL至1
nullableId = -1NULL(因为与NULL的任何比较都会返回NULL
所以这个表达式:

(nullableId IS NULL) | (nullableId = -1)


计算为NULL,并且由于t不是TRUE,因此不返回这些行。
但是,当nullableId = -1时,表达式的计算结果为:

0 | 1 = 1


因此,返回所有带有nullableId = -1的行。
您可以在如下表中看到此行为:

create table demo(nullableId int);
insert into demo(nullableId) values
(1), (null), (-1), (2);


查询:

SELECT *,
  (nullableId IS NULL),
  (nullableId = -1),
  (nullableId IS NULL) | (nullableId = -1)
FROM demo


返回:

| nullableId | (nullableId IS NULL) | (nullableId = -1) | (nullableId IS NULL) | (nullableId = -1) |
| ---------- | -------------------- | ----------------- | ---------------------------------------- |
| 1          | 0                    | 0                 | 0                                        |
| null       | 1                    | null              | null                                     |
| -1         | 0                    | 1                 | 1                                        |
| 2          | 0                    | 0                 | 0                                        |

10-05 19:19