Sql server 在WHERE子句中使用可为空的列

Sql server 在WHERE子句中使用可为空的列,sql-server,tsql,static-analysis,datadude,Sql Server,Tsql,Static Analysis,Datadude,假设SQL Server中的表定义如下: CREATE TABLE MyTable ( Id UNIQUEIDENTIFIER NULL, Info VARCHAR(MAX) ) 和一个查询: DECLARE @id UNIQUEIDENTIFIER DECLARE @info VARCHAR(MAX) IF @id IS NOT NULL BEGIN SELECT @info = Info FROM MyTable WHERE Id = @id END 在这

假设SQL Server中的表定义如下:

CREATE TABLE MyTable (
  Id   UNIQUEIDENTIFIER NULL,
  Info VARCHAR(MAX)
)
和一个查询:

DECLARE @id UNIQUEIDENTIFIER
DECLARE @info VARCHAR(MAX)
IF @id IS NOT NULL
BEGIN
  SELECT @info = Info
    FROM MyTable
    WHERE Id = @id
END
在这种情况下,Visual Studio静态代码分析器会产生以下错误:

警告:SR0007: Microsoft。性能:可为空 列可能导致最终结果被忽略 谓词的计算结果为NULL

我看不出这里有什么问题。错误与性能有关;MSDN说我应该使用ISNULL()——但是与NULL的equals比较总是错误的,对吗?是我遗漏了什么,还是警告错了

IF @id IS NOT NULL
应替换为

IF ISNull(@id, -1) <> -1
如果为空(@id,-1)-1

我认为分析器可能没有考虑您的IF语句

您的代码在我看来似乎是正确的。

@Raj:“IF ISNull(@id,-1)-1”


我不会这样做,因为它实际上替换了表条目

我认为它指的是WHERE子句。这意味着参数和列都可以为NULL,在这种情况下,WHERE子句的计算结果不再为true/false。通过将可为null的列集中到一个始终定义有值的列中(通过ISNULL),从逻辑角度看,您的状态更好


另一方面,空值可能会使查询速度变慢。

空值比较取决于设置

当“设置ANSI_null”处于启用状态时,所有与null值的比较结果均为未知值

当SET ANSI_NULLS处于启用状态时,使用WHERE column_name=NULL的SELECT语句
即使列_name中有空值,也返回零行。
使用WHERE column\u name NULL的SELECT语句返回零行,即使column\u name中没有nnull值。

当SET ANSI_NULLS关闭时,等于(=)和不等于()比较运算符不符合ISO标准。


这是

我认为这是一个虚假的警告-你能在个案的基础上抑制它,还是完全抑制那个特定的警告

当你这样做时会发生什么

CREATE TABLE MyTable (
  Id   UNIQUEIDENTIFIER NOT NULL,
  Info VARCHAR(MAX)
)

@Raj这不是和“如果@id不为null”完全一样吗?更改它有什么意义?该代码实际上甚至不会编译,因为@id是一个GUID,而不是INT.oops。对不起,我以为id是一个整数。消息抱怨的是一个可为null的列,而不是一个可为null的参数。另外,如果我将WHERE子句更改为:
Id不为NULL且Id=@Id
@Id不为NULL且Id=@Id
,则消息仍然存在。啊哈!它试图抱怨的是它们都是空的——除非我在where子句中用if或更多细节排除了这一点,否则分析器不会接受它。我不知道你说的空值使查询变慢是什么意思。您的意思是可为空的列比不可为空的列慢吗?或者你说的是ISNULL?我是说一个可为null的列比一个不可为null的列在获取/处理上要慢。但是我没有什么可以支持的,所以请用一粒可以为零的盐来支持=但不幸的是,我是新手,没有足够的分数(或声誉)来评论:(将其更改为NOTNULL可消除警告。我可能最终会抑制该消息;我只想确保我完全理解它首先发生的原因,并报告它是否真的是一个bug。