Sql WHERE子句使用可能为NULL的值

Sql WHERE子句使用可能为NULL的值,sql,sql-server,tsql,null,Sql,Sql Server,Tsql,Null,我需要这样做: DECLARE @firstname VARCHAR(35) DECLARE @lastname VARCHAR(35) SELECT * FROM Customers WHERE Firstname = @firstname AND Lastname = @lastname 问题是@firstname和@lastname有时可能为NULL。在这些情况下,上面的查询将无法找到匹配的行,因为NULL永远不等于NULL 如果这些变量中有一个为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,我希望返回一个匹配项。但是,当然,SQLServer使用IS来比较NULL。在上面的例子中,如果其中一个值为NULL,则不认为它是匹配的


有什么方法可以做到这一点吗?

只需使用和/或逻辑即可

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来执行此操作。这是因为基于集合的操作将空值比较为相等

编译器将下降到一个IS比较,不应该有任何性能影响

声明@firstname VARCHAR35 声明@lastname VARCHAR35 挑选* 来自客户c 如果存在,请选择c.Firstname、c.Lastname 横断 选择@firstname、@lastname 逻辑是:对于每一行,创建一个包含两个值的单行虚拟表,将其与两个变量相交,并且必须有一个结果

对于语义,将EXISTS改为notexists,而不是改为EXCEPT,我发现前者的优化效果更好


为了这个把戏。

这能回答你的问题吗@查理脸:不是真的。我接受的答案回答得更好。@JonathanWood实际上Charlieface的建议比我的建议更好。更简单,更可扩展。就像你所做的那样。我发现我的版本没有那么麻烦@DaleK我不认为在大多数情况下性能有太大的不同,只是更整洁,尤其是有很多比较。@Charlieface公平地说,我不认为这是一个骗局,OP是问如何做到这一点,而Sugged dupe是问如何改进。你知道INTERSECT/EXCEPT的把戏吗?见下文和保罗·怀特的文章。请注意,您的版本也会编译到查询计划中的IS