Việc bạn so sánh nó với một integer
biến là không liên quan.
Kế hoạch cho COUNT
luôn luôn có một CONVERT_IMPLICIT(int,[ExprNNNN],0))
nơi ExprNNNN
là nhãn cho biểu đại diện cho các kết quả của sự COUNT
.
Giả định của tôi luôn luôn là mã COUNT
cuối cùng gọi cùng mã COUNT_BIG
và diễn viên là cần thiết để chuyển đổi bigint
kết quả của mã đó trở lại int
.
Trong thực tế COUNT_BIG(*)
thậm chí không được phân biệt trong kế hoạch truy vấn từ COUNT(*)
. Cả hai hiện lên như Scalar Operator(Count(*))
.
COUNT_BIG(nullable_column)
không được phân biệt trong kế hoạch thực hiện từ COUNT(nullable_column)
nhưng sau này vẫn nhận được một diễn viên ngầm quay trở lại int
.
Một số bằng chứng cho thấy đây là trường hợp dưới đây.
WITH
E1(N) AS
(
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
) -- 1*10^1 or 10 rows
, E2(N) AS (SELECT 1 FROM E1 a, E1 b) -- 1*10^2 or 100 rows
, E4(N) AS (SELECT 1 FROM E2 a, E2 b) -- 1*10^4 or 10,000 rows
, E8(N) AS (SELECT 1 FROM E4 a, E4 b) -- 1*10^8 or 100,000,000 rows
, E16(N) AS (SELECT 1 FROM E8 a, E8 b) -- 1*10^16 or 10,000,000,000,000,000 rows
, T(N) AS (SELECT TOP (2150000000)
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS N FROM E16)
SELECT COUNT(CASE WHEN N < 2150000000 THEN 1 END)
FROM T
OPTION (MAXDOP 1)
Điều này mất khoảng 7 phút để chạy trên máy tính để bàn của tôi và trả về như sau
Msg 8115, Cấp 16, Bang 2, Dòng 1
Lỗi tràn số học chuyển đổi biểu thức sang kiểu dữ liệu int.
Cảnh báo: Giá trị Null được loại bỏ bằng thao tác tổng hợp hoặc hoạt động SET khác.
Điều đó chỉ ra rằng COUNT
phải tiếp tục sau khi int
đã tràn (tại 2147483647) và hàng cuối cùng (2150000000) đã được xử lý bởi COUNT
nhà điều hành dẫn đến thông báo về việc NULL
được trả lại.
Bằng cách so sánh thay thế COUNT
biểu thức bằng SUM(CASE WHEN N < 2150000000 THEN 1 END)
trả về
Msg 8115, Cấp 16, Bang 2, Dòng 1
Lỗi tràn số học chuyển đổi biểu thức sang kiểu dữ liệu int.
không có ANSI
cảnh báo về NULL
. Từ đó tôi kết luận rằng sự cố tràn đã xảy ra trong trường hợp này trong quá trình tổng hợp trước khi đạt được hàng 2.150.000.000.
ScalarOperator
giá trị được hiển thị trong cửa sổ thuộc tính SSMS.