Nie ma znaczenia fakt, że porównujesz ją ze integer
zmienną.
Plan COUNT
zawsze ma CONVERT_IMPLICIT(int,[ExprNNNN],0))
gdzie ExprNNNN
jest etykieta dla wyrażenia reprezentującego wynik COUNT
.
Zawsze zakładałem, że kod COUNT
tylko wywołuje ten sam kod co COUNT_BIG
i rzutowanie jest konieczne, aby przekonwertować bigint
wynik tego z powrotem na int
.
W rzeczywistości COUNT_BIG(*)
nawet nie rozróżnia się w planie zapytań COUNT(*)
. Oba pojawiają się jako Scalar Operator(Count(*))
.
COUNT_BIG(nullable_column)
wyróżnia się w planie wykonania od, COUNT(nullable_column)
ale ten drugi wciąż wraca do domyślnego rzutu int
.
Niektóre dowody na to, że tak jest, znajdują się poniżej.
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)
Uruchomienie na moim pulpicie zajmuje około 7 minut i zwraca następujące
Msg 8115, poziom 16, stan 2, wiersz 1
Błąd przepełnienia arytmetycznego podczas konwersji wyrażenia na typ danych int.
Ostrzeżenie: Wartość zerowa jest eliminowana przez agregację lub inną operację SET.
Co wskazuje, że COUNT
ciąg dalszy musi nastąpić po int
przepełnieniu (w 2147483647), a ostatni wiersz (2150000000) został przetworzony przez COUNT
operatora, co spowodowało wyświetlenie komunikatu o zwrocie NULL
.
Dla porównania, zastępując COUNT
wyrażenie SUM(CASE WHEN N < 2150000000 THEN 1 END)
zwrotami
Msg 8115, poziom 16, stan 2, wiersz 1
Błąd przepełnienia arytmetycznego podczas konwersji wyrażenia na typ danych int.
bez ANSI
ostrzeżenia o NULL
. Z tego wnioskuję, że przepełnienie nastąpiło w tym przypadku podczas samej agregacji przed osiągnięciem wiersza 2 150 000 000.
ScalarOperator
wartość pokazaną w oknie właściwości SSMS.