我有一个包含以下字段的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
的值有条件地构建查询?
答案 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))
请注意,由于您没有使用命名参数,因此必须指定所有参数两次。