2017-08-28 118 views
7

Mã này hoạt động ok:Operand kiểu dữ liệu NULL không hợp lệ cho max hành

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; 

đầu ra:

fk   maxx 
----------- ----------- 
1   NULL 

với:

Warning: Null value is eliminated by an aggregate or other SET operation.

Nhưng mã này:

select fk, max(a) maxx 
    from (values(1, null), (1, null)) x(fk, a) 
    group by fk; 

cho lỗi:

Msg 8117, Level 16, State 1, Line 5 Operand data type NULL is invalid for max operator.

Trong cả hai trường hợp máy chủ sql tính toán max từ nullnull? Phải không?

+2

Bạn có thể thực hiện công việc thứ hai bằng cách truyền một cách rõ ràng null vào một kiểu dữ liệu. 'select fk, max (a) maxx từ (giá trị (1, CAST (NULL AS varchar (25))), (1, CAST (NULL AS varchar (25)))) x (fk, a) nhóm theo fk; 'Bạn không thể nhận được tối đa của null khi datatype cho cột là không rõ. Bạn sẽ lưu ý khi bạn thử và tạo một bảng chỉ có null; nó cũng không thành công bởi vì một kiểu dữ liệu không xác định. – xQbert

Trả lời

9

Trong trường hợp đầu tiên, bạn ngầm định rõ một kiểu dữ liệu, cụ thể là một số nguyên. Điều này được suy ra từ then sẽ không bao giờ đạt được. Thực tế là then sẽ không được thực thi, không quan trọng đối với máy chủ sql. In fact, máy chủ cách sql xác định kiểu trả về: "các precedence loại cao nhất từ ​​tập các loại trong result_expressionselse_result_expression tùy chọn". Vì vậy, kiểu trả về được chọn trước khi thực hiện thực tế thực thi, từ tất cả các kiểu dữ liệu tiềm năng được trả lại trong thenelse. nói cách khác, trước khi máy chủ sql 'nhận ra' rằng một số câu lệnh không thể đạt được.

Vì kiểu dữ liệu được biết, max có thể được áp dụng.

Trong trường hợp thứ hai bạn không chỉ định kiểu dữ liệu, vì vậy máy chủ sql không thể biết cách triển khai max. A max cho varchar khác với số max cho số nguyên.

1

Điều đó gọn gàng. Theo tôi, có lẽ nên được chuyển đổi hoàn toàn thành int.

Các tài liệu đề cập đến điều này cho 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)


Cả hai biến các giá trị null một 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 demo: http://rextester.com/VWMT9189

lợi nhuận

+-----------+------+ 
| name | name | 
+-----------+------+ 
| MyNullCol | int | 
| a   | int | 
+-----------+------+ 
+0

Vâng, nó rất lạ. Bài kiểm tra của tôi 'select fk, một INTO #T từ (giá trị (1, null), (1, null)) x (fk, a) exec tempdb.sys.sp_columns #T drop table # T' cũng cho tôi' int' cho 'a' ... –

+0

Điểm tốt, mặc dù theo ý kiến ​​của tôi, các ví dụ của bạn sẽ đưa ra một lỗi. Nếu bạn cố gắng tạo một bảng với 'null' làm kiểu dữ liệu, nó cũng không được chuyển đổi thành' int'. Nhưng đó là cách máy chủ sql được xây dựng, tôi cho là vậy. – HoneyBadger

+0

Có thể diễn viên này chỉ xảy ra khi chèn dữ liệu xảy ra. –

Các vấn đề liên quan