在SQL查询中检查列的null或值的有效方法是什么。考虑具有整数列table
的sql表column
,其具有索引。 @value
可以是某个整数或null ex:16或null。
查询1:不确定,但似乎不应该依赖SQL中的短路。但是,当@value
为某个整数或null时,下面的查询始终可以正常工作。
select * from
table
where (@value is null or column = @value)
以下查询是上述查询的扩展版本。它也正常工作。
select * from
table
where ((@value is null)
or (@value is not null and column = @value))
以上2个查询是否会利用索引?
查询2:以下查询将列与非空@value
进行比较,否则将列column
与其自身进行比较,该列始终为true并返回所有内容。它也正常工作。这个查询会利用索引吗?
select * from
table
where (column = isnull(@value, column))
最好的方法是什么?
注意:如果答案因数据库而异,我对MS-SQL感兴趣。
答案 0 :(得分:2)
在过去的几天里,这个问题的变化多次出现(为什么这些事情总是在小组中发生?)。简而言之,是的,SQL Server将使用已知值创建查询计划的逻辑短路。因此,如果您在设置变量的脚本中有该代码,那么我认为它应该使逻辑短路(测试以确保)。但是,如果它在存储过程中,则SQL Server将提前创建查询计划,并且它不知道它是否可以使查询短路,因为它在生成时不知道参数值查询计划。
无论是否短路,SQL Server都应该能够使用索引,如果这是查询的唯一部分。如果变量为NULL,那么您可能不希望SQL Server使用索引,因为它将是无用的。
如果您在存储过程中,那么最好的办法是在查询中使用OPTION(RECOMPILE)。这将导致SQL Server每次都创建一个新的查询计划。这有点开销,但收益通常会大大超过这一点。这仅适用于SQL 2008,甚至只适用于某些后续的Service Pack。在使用它之前,RECOMPILE存在一个错误。有关更多信息,请查看Erland Sommarskog关于此主题的great article。具体来说,您需要查看静态SQL部分。
答案 1 :(得分:1)
为了澄清一点,SQL并不像我们在基于C语言中所知的那样短路。看起来像是短路的是SQL Server三元逻辑TRUE OR NULL评估为TRUE
TRUE OR NULL ===> TRUE
TRUE AND NULL ===> NULL
例如:
if 1=null or 1=1 print 'true' else print 'false'
if 1=null and 1=1 print 'true' else print 'false'