WHERE 子句使用可能为 NULL 的值
WHERE clause using values that could be NULL
我需要做这样的事情:
DECLARE @firstname VARCHAR(35)
DECLARE @lastname VARCHAR(35)
SELECT *
FROM Customers
WHERE Firstname = @firstname AND Lastname = @lastname
问题是 @firstname
和 @lastname
有时可能是 NULL
。在这些情况下,上面的查询将无法找到匹配的行,因为 NULL
永远不等于 NULL
.
如果这些变量之一是 NULL
,如果数据库中的对应值也是 NULL
,我想 return 匹配。但是,当然,SQL 服务器使用 IS
来比较 NULL
。如果上述示例中任一值为 NULL
,则不认为是匹配项。
有什么办法可以做到吗?
只需使用 AND/OR 逻辑,例如
SELECT *
FROM Customers
WHERE ((Firstname IS NULL AND @firstname IS NULL) OR Firstname = @firstname)
AND ((Lastname IS NULL AND @lastname IS NULL) OR Lastname = @lastname);
您可以在相关子查询中利用 INTERSECT
来执行此操作。 这是可行的,因为基于集合的操作将 NULL
比较为相等。
编译器将 automatically compile this 进行 IS
比较,应该不会对性能造成任何影响。
DECLARE @firstname VARCHAR(35)
DECLARE @lastname VARCHAR(35)
SELECT *
FROM Customers c
WHERE EXISTS (SELECT c.Firstname, c.Lastname
INTERSECT
SELECT @firstname, @lastname)
逻辑是:对于每一行,用两个值创建一个单行虚拟table,将它与两个变量相交,并且必须有一个结果。
对于<>
语义,将EXISTS
更改为NOT EXISTS
,而不是更改为EXCEPT
,我发现前者优化得更好。
All credit to Paul White 这个技巧。
我需要做这样的事情:
DECLARE @firstname VARCHAR(35)
DECLARE @lastname VARCHAR(35)
SELECT *
FROM Customers
WHERE Firstname = @firstname AND Lastname = @lastname
问题是 @firstname
和 @lastname
有时可能是 NULL
。在这些情况下,上面的查询将无法找到匹配的行,因为 NULL
永远不等于 NULL
.
如果这些变量之一是 NULL
,如果数据库中的对应值也是 NULL
,我想 return 匹配。但是,当然,SQL 服务器使用 IS
来比较 NULL
。如果上述示例中任一值为 NULL
,则不认为是匹配项。
有什么办法可以做到吗?
只需使用 AND/OR 逻辑,例如
SELECT *
FROM Customers
WHERE ((Firstname IS NULL AND @firstname IS NULL) OR Firstname = @firstname)
AND ((Lastname IS NULL AND @lastname IS NULL) OR Lastname = @lastname);
您可以在相关子查询中利用 INTERSECT
来执行此操作。 这是可行的,因为基于集合的操作将 NULL
比较为相等。
编译器将 automatically compile this 进行 IS
比较,应该不会对性能造成任何影响。
DECLARE @firstname VARCHAR(35)
DECLARE @lastname VARCHAR(35)
SELECT *
FROM Customers c
WHERE EXISTS (SELECT c.Firstname, c.Lastname
INTERSECT
SELECT @firstname, @lastname)
逻辑是:对于每一行,用两个值创建一个单行虚拟table,将它与两个变量相交,并且必须有一个结果。
对于<>
语义,将EXISTS
更改为NOT EXISTS
,而不是更改为EXCEPT
,我发现前者优化得更好。
All credit to Paul White 这个技巧。