我最近在一次演讲中看到过这个例子。运行如下查询时:
SELECT COUNT(NULL)
您会收到以下错误:
操作数数据类型 NULL 对于计数运算符无效。
运行以下命令时:
SELECT COUNT(1/NULL)
结果是 0,即使除法本身产生 NULL。如果交换 1 和 NULL,也会发生同样的情况。
但是,如果您这样做:
SELECT COUNT(NULL/NULL)
您再次收到与第一个查询相同的错误(除法本身是合法的,产生 NULL(。
谁能解释一下sql server是如何工作的来给出这些结果的?
在 SQL Server 中,某些聚合函数(如 COUNT、MIN、MAX(和函数(如 DATEADD(需要数据类型。NULL
,本身没有,所以这会给你一个错误:
SELECT COUNT(NULL) -- Operand data type NULL is invalid for count operator.
同样适用于:
SELECT COUNT(NULL/NULL)
对于1/NULL
,数据类型为 INT,值为 NULL,因此可以这样做:
SELECT COUNT(1/NULL) -- 0
同样适用于:
SELECT COUNT(CAST(NULL AS INT)) -- 0
这实际上是一个编译器错误。运行批处理时,将分析 T-SQL,并在此时(而不是在执行时(绘制语句SELECT COUNT(NULL);
和SELECT COUNT(NULL/NULL);
上的错误。
如果您运行下面的批处理,您将很快看到以下内容:
PRINT 'testing 1'
SELECT COUNT(NULL); --Error at compile
GO
PRINT 'testing 2'
SELECT COUNT(1/NULL); --Runs
GO
PRINT 'testing 3'
SELECT COUNT(NULL/NULL); --Error at compile
GO
PRINT 'testing 4'
SELECT COUNT(0/0); --Error at run time
请注意,testing 1
和testing 3
语句永远不会显示。
值NULL
本身没有数据类型。表达式的所有边都NULL
的表达式实际上具有未知的数据类型。
如果要为NULL
提供数据类型,则不会发生此问题:
PRINT 'testing 5'
SELECT COUNT(CONVERT(int,NULL));
GO
PRINT 'testing 6'
DECLARE @N int;
SELECT COUNT(@N);
问题出在所涉及的数据类型上。如果我们运行以下命令,我们可以看到 NULL 本身没有数据类型:
SELECT SQL_VARIANT_PROPERTY(NULL,'BaseType')
这对应于您看到的错误。
我们可以强制 NULL 使用强制转换选择数据类型,在这种情况下,错误得到解决:
SELECT COUNT(cast(NULL as int))