这段代码工作正常:
select fk, max(case when 1 = 0 then 1 else null end) maxx
from (values(1, null), (1, null)) x(fk, a)
group by fk;
输出:
fk maxx
----------- -----------
1 NULL
跟:
Warning: Null value is eliminated by an aggregate or other SET operation.
但是这个代码:
select fk, max(a) maxx
from (values(1, null), (1, null)) x(fk, a)
group by fk;
给出错误:
Msg 8117, Level 16, State 1, Line 5
Operand data type NULL is invalid for max operator.
在这两种情况下,sql 服务器都会从null
和null
中计算max
?不是吗?
在第一种情况下,你隐式指定一个数据类型,即一个整数。这是从永远不会达到的then
推断出来的。then
不会被执行的事实对于 sql 服务器来说并不重要。事实上,sql Server 确定返回类型的方式是:">result_expressions中的类型集中优先级最高的类型以及可选的else_result_expression"。因此,返回类型是在实际执行之前从then
和else
中返回的所有潜在数据类型中选择的。换句话说,在SQL Server"意识到"某些语句不可能被访问之前。
由于数据类型是已知的,因此可以应用max
。
在第二种情况下你没有指定数据类型,所以sql服务器不知道如何实现max
。varchar
的max
不同于整数的max
。
这很整洁。在我看来,它可能应该隐式转换为int
.
文档在inserts
中提到了这一点:
多行
insert
语句中指定的值遵循union all
语法的数据类型转换属性。 - 表值构造函数 (事务处理-SQL)
两者都将null
值转换为int
:
select null as MyNullCol
into dbo.tmp
union all
select null as MyNullCol
select fk, a
into dbo.tmp2
from (values(1, null), (1, null)) x(fk, a)
select c.name, t.name
from sys.columns c
inner join sys.types t
on c.user_type_id = t.user_type_id
where c.name in ('a','mynullcol')
Rextester 演示:http://rextester.com/VWMT9189
返回
+-----------+------+
| name | name |
+-----------+------+
| MyNullCol | int |
| a | int |
+-----------+------+