2

我有一个包含以下字段的 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

4

3 回答 3

4

但我无法编辑查询说entrance IS ?,因为当我传递除NULL.

是的你可以。这不是标准 SQL,而是 SQLite 扩展。从SQLite 查询语言

IS 和 IS NOT 运算符的工作方式与 = 和 != 类似,除非其中一个或两个操作数为 NULL。在这种情况下,如果两个操作数都为 NULL,则 IS 运算符的计算结果为 1(真),而 IS NOT 运算符的计算结果为 0(假)。如果一个操作数为 NULL 而另一个不是,则 IS 运算符的计算结果为 0(假)并且 IS NOT 运算符为 1(真)。IS 或 IS NOT 表达式不可能计算为 NULL。运算符 IS 和 IS NOT 与 = 具有相同的优先级。

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

于 2013-06-05T10:39:33.017 回答
2

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

你可以用一个魔术字符串来表示 NULL——空字符串通常可以解决问题——然后这样做:

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

如果您需要将空字符串视为与 NULL 不同,则 的输出uuidgen将提供一个几乎可以保证不匹配任何其他内容的魔术字符串(除非您正在执行一些自反编码):

    COALESCE(entrance, '4F939D9A-F91E-4693-8DD5-F631FB11F061') = ? AND
于 2013-06-05T10:33:12.793 回答
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))

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

于 2013-06-05T10:30:32.760 回答