Любопытное противоречивое поведение из SQL Server в предложениях оконных функций? - PullRequest
7 голосов
/ 26 августа 2011

Задавая другой вопрос , я обнаружил, что SQL Server (случается как в 2005, так и в 2008 году), похоже, имеет странное противоречивое поведение при работе с операторами CASE в предложениях оконных функций.Следующий код выдает ошибку:

declare @t table (SortColumn int)
insert @t values (1), (2), (3)
declare @asc bit
set @asc = 0

select  row_number() over (order by
            case when 1=1 then SortColumn end asc,
            case when 1=0 then SortColumn end desc) RowNumber
,       *
from    @t

Ошибка: Оконные функции не поддерживают константы как выражения предложения ORDER BY. Я полагаю, это потому, что оператор case может вычислить какNULL, который является константой.Как и следовало ожидать, этот код выдает ту же ошибку:

declare @t table (SortColumn int)
insert @t values (1), (2), (3)
declare @asc bit
set @asc = 0

select  row_number() over (order by
            NULL asc,
            NULL desc) RowNumber
,       *
from    @t

... предположительно по той же причине.Однако этот код не выдает ошибку:

declare @t table (SortColumn int)
insert @t values (1), (2), (3)
declare @asc bit
set @asc = 0

select  row_number() over (order by
            case when @asc=1 then SortColumn end asc,
            case when @asc=0 then SortColumn end desc) RowNumber
,       *
from    @t

Единственное отличие здесь от первого кодового блока состоит в том, что я переместил один из условных операндов case операторов в переменную @asc.Теперь это работает отлично.Но почему?Операторы case могут по-прежнему принимать значение NULL, которое является константой, поэтому оно не должно работать ... но оно работает.Это как-то согласуется или это особый случай, введенный Microsoft?

Все это можно проверить, поиграв с этим запросом .


Обновление: Это ограничение относится не только к предложениям OVER (хотя они дают другую ошибку) - оно применяется ко всем предложениям ORDER BY начиная с SQL Server 2005. Вот запрос , который также показывает ограничение с помощью регулярного предложения SELECT * ORDER BY.

Ответы [ 2 ]

4 голосов
/ 27 августа 2011

В электронных книгах указано, что «столбец сортировки может содержать выражение, но когда база данных находится в режиме совместимости с SQL Server (90), выражение не может преобразоваться в константу».однако он не определяет «константу».

Из размышлений об этом и некоторых экспериментов становится ясно, что это означает выражение, для которого буквальное значение константы может быть успешно вычислено во время компиляции.

/*Works - Constant at run time but SQL Server doesn't do variable sniffing*/
DECLARE @Foo int
SELECT ROW_NUMBER() OVER (ORDER BY @Foo) 
FROM master..spt_values 

/*Works - Constant folding not done for divide by zero*/
SELECT ROW_NUMBER() OVER (ORDER BY $/0) 
FROM master..spt_values 

/*Fails - Windowed functions do not support 
   constants as ORDER BY clause expressions.*/
SELECT ROW_NUMBER() OVER (ORDER BY $/1) 
FROM master..spt_values 
0 голосов
/ 26 августа 2011

Оценки в вашем первом примере никогда не изменятся.

Вы сравниваете константу с константой, которая постоянно приводит к константе.

1=1 всегда будет TRUE.
1=0 всегда будет FALSE.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...