比较 SQLite 查询中两个可能为 NULL 的值

Son*_*Ex2 3 python sqlite sql-null

我有一个 SQLite 查询,如:

SELECT max(e), url, branch FROM (SELECT max(T1.entry) e, T1.url, T1.branch FROM repo_history T1
                                                        WHERE (SELECT active FROM repos T2 WHERE url = T1.url AND branch = T1.branch AND project = ?1)
                                                        GROUP BY T1.url, T1.branch
                                                        UNION
                                                        SELECT null, T3.url, T3.branch FROM repos T3 WHERE active AND project = ?1 )
                               GROUP BY url ORDER BY e
Run Code Online (Sandbox Code Playgroud)

请注意,该?1参数出现了两次。无论如何,在某些情况下,它可以为空(None在 python 中,据我所知,NULL在 SQLite 中变成了)。这是一个问题,因为我不了解 null 处理,但基本上我没有得到任何回报。

那么,我如何处理where "project" = ?1什么时候?1是 NULL?我想避免对它进行 2 个单独的查询。我环顾四周,但我只能找到关于IS NULL/ 的东西IS NOT NULL,这对我不起作用,因为我不是要检查列是否为空或不为空,而是要检查两个可空值是否匹配,无论它们为空还是不为空。

kxr*_*kxr 8

In SQLite you can use the IS operator instead of = for NULL tolarant comparisons. Works also with ? insertions (unlike MikeT meant).

Python example:

>>> c.execute('SELECT * FROM mytable WHERE userid = ? AND recipe = ?', (3, None)).fetchall()
[]

>>> c.execute('SELECT * FROM mytable WHERE userid = ? AND recipe IS ?', (3, None)).fetchall()
[<Row object>, <Row object>]

>>> c.execute('SELECT * FROM mytable WHERE userid = ? AND recipe is ?', (3, 'TestRecipe')).fetchall()
[<Row object>]
Run Code Online (Sandbox Code Playgroud)

The IS and IS NOT operators work like = and != except when one or both of the operands are NULL. In this case, if both operands are NULL, then the IS operator evaluates to 1 (true) and the IS NOT operator evaluates to 0 (false). If one operand is NULL and the other is not, then the IS operator evaluates to 0 (false) and the IS NOT operator is 1 (true). It is not possible for an IS or IS NOT expression to evaluate to NULL. Operators IS and IS NOT have the same precedence as =.

For older MySQL / Mariadb versions at least the NULL tolarant comparison operator is <=> and in PostgreSQL its IS NOT DISTINCT FROM .

The PostgreSQL variant is defined in the SQL:2003 standard. For provisional compatibility maybe insert the suitable operator from a Python dict ...