2017-08-28 94 views
7

无效此代码工作正常:操作数的数据类型NULL是最大运营商

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 Server的计算从nullnullmax?不是吗?

+2

您可以通过显式将null转换为数据类型来进行第二个工作。 (1,CAST(NULL AS varchar(25))),(1,CAST(NULL AS varchar(25))))x(fk,a) group by fk;'当列的数据类型未知时,您无法获得最大值null。当你尝试创建一个只有空值的表时,你会注意到;它也会失败,因为数据类型是未知的。 – xQbert

回答

9

在第一种情况下,您隐式指定数据类型,即整数。这是从then推断,永远不会达到。事实上,then不会被执行,对于sql服务器无关紧要。 In fact,sql server确定返回类型的方式:“result_expressionions可选else_result_expression”中类型集合的最高precedence类型“。所以返回类型在实际执行之前选择,从thenelse中返回的所有潜在数据类型中选择返回类型。换句话说,在sql server'意识到'某些语句不可能被达到之前。

由于数据类型已知,因此可以应用max

在第二种情况下,您没有指定数据类型,所以sql server无法知道如何实现max。对于varchar,A max与整数的max不同。

1

这是整齐。在我看来,它可能应该隐含转换为int

该文档提到这一点对于inserts

the values specified in a multi-row insert statement follow the data type conversion properties of the union all syntax. - Table Value Constructor (Transact-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 | 
+-----------+------+ 
+0

是的,这很奇怪。我的测试'select fk,INTO #T from(values(1,null),(1,null))x(fk,a)exec tempdb.sys.sp_columns #T drop table#T' also give me'int'为'a' ... –

+0

好点,虽然在我看来你的例子应该给出一个错误。如果您尝试创建一个具有'null'作为数据类型的表,它也不会被隐式转换为'int'。但是,我想这就是SQL服务器的构建方式。 – HoneyBadger

+0

可能只有在发生数据插入时才会发生这种转换。 –