为什么匹配NULL需要SQL中的特殊语法,我该如何解决它?

时间:2013-06-05 10:13:57

标签: sql

我有一个包含以下字段的SQLite3表:

id INTEGER PRIMARY KEY,
street_name TEXT NOT NULL,
house_number INTEGER NOT NULL,
entrance TEXT DEFAULT NULL,
postal_code INTEGER NOT NULL,
city TEXT NOT NULL

正如您所看到的,入口可以是NULL,默认情况下甚至设置为该值。当我试图检查特定地址是否存在时,这是一个问题:

SELECT 1 FROM street_addresses
WHERE
    street_name=? AND
    house_number=? AND
    entrance=? AND
    postal_code=? AND
    city=?

如果我将NULL传递到入口字段,则无论什么原因,查询都不会产生任何结果,因为entrance=NULL无效。相反,我必须使用entrance IS NULL,但我无法编辑查询以说出entrance IS ?,因为当我传递NULL以外的任何内容时,这不起作用。

有没有什么方法可以解决此除了根据entrance的值有条件地构建查询?

3 个答案:

答案 0 :(得分:4)

  

但我无法编辑查询以说出entrance IS ?,因为当我传递NULL以外的其他内容时,这不起作用。

是的,你可以。这不是标准SQL,而是SQLite扩展。来自SQLite Query Language

  

IS和IS NOT运算符的工作方式类似于=和!=,除非一个或两个操作数都为NULL。在这种情况下,如果两个操作数均为NULL,则IS运算符求值为1(true),IS NOT运算符求值为0(false)。如果一个操作数为NULL而另一个操作数不为NULL,则IS运算符的计算结果为0(false),IS NOT运算符为1(true)。 IS或IS NOT表达式无法计算为NULL。运算符IS和IS的优先级与=。

不同

标准SQL中也存在相同的操作,但使用不同的语法:它看起来像a IS NOT DISTINCT FROM b。此语法尚未得到广泛支持,但大多数数据库都有某种方式来表达它。 a IS b是SQLite变体。

答案 1 :(得分:2)

(NULL是一个彻底破碎的概念,但是现在不要去那里......)

你可以用魔术字符串代替NULL - 空字符串通常可以解决问题 - 并执行此操作:

WHERE
    …
    COALESCE(entrance, '') = ? AND
    …

如果你需要将空字符串视为不同于NULL,uuidgen的输出将提供一个神奇的字符串,几乎可以保证不与其他任何东西匹配(除非你正在做一些自反射编码):

    COALESCE(entrance, '4F939D9A-F91E-4693-8DD5-F631FB11F061') = ? AND

答案 2 :(得分:1)

SQLite如何处理这一点没有什么特别之处,所有(普通)关系数据库都使用这种语法。

您可以将代码更改为:

SELECT 1 FROM street_addresses
WHERE
    (street_name=?  OR (street_name is null  and ? is null)) AND
    (house_number=? OR (house_number is null and ? is null)) AND
    (entrance=?     OR (entrace is null      and ? is null)) AND
    (postal_code=?  OR (postal_code is null  and ? is null)) AND
    (city=?         OR (city is null         and ? is null))

请注意,由于您没有使用命名参数,因此必须指定所有参数两次。