Будет ли SQL Server постоянно замыкаться в этом конкретном случае? - PullRequest
2 голосов
/ 26 апреля 2011

Во-первых, позвольте мне сказать, что я полностью знаю, что сервер SQL не оценивает короткое замыкание Он может, если посчитает нужным, из-за плана выполнения, но лучше не догадываться.

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

declare @customerId int

set @customerId = null
select * from customer where ( (@customerId Is Null) Or CustomerId=@customerId)

CustomerId - это PK (int), не обнуляемый

ВОПРОС: Кто-нибудь знает, будет ли двигатель всегда выбирать левую сторону в этом случае или мы действительно закончим проверкой, если CustomerId = null с правой стороны для каждой строки. Я предполагаю, что это не гарантированно сработает, так как правая часть может быть «менее избирательной», но мне любопытно, если sql-сервер видит нулевое значение и знает в каждом случае, как это, использовать левую часть из-за нулевого значения заявление. Я считаю, что это лучше всего сделать в качестве примера ниже (если вы можете улучшить запрос ниже, пожалуйста, сделайте!), Но мне просто любопытно в этом случае для целей обучения, если кто-нибудь знает о последовательном внутреннем поведении здесь. Он работает во всех моих случаях, но также является первичным ключом, который не обнуляется, поэтому может быть, это всегда работает. если это обнуляемый тип, то правая часть может быть менее избирательной, чем левая, и мы сейчас имеем дело с другой ситуацией.

Мой план выполнения в обоих запросах выглядит одинаково.

в любом случае - потенциально лучший способ написать это (пожалуйста, улучшите его, если можете)



declare @customerId  int
set @customerId = null

select * from Customer
where 

case 
    when @customerId is null then 1
end = 1

or 
case 
    when @customerId is not null then @customerId
    else -1
end = CustomerId

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

спасибо!

Ответы [ 2 ]

3 голосов
/ 26 апреля 2011

Вы можете попробовать это:

...WHERE CustomerId = COALESCE(@customerId, CustomerId)

или, если хотите, «расширенную» версию COALESCE:

...WHERE CustomerId = CASE
                        WHEN @customerId IS NULL THEN CustomerId
                        ELSE @customerId
                      END
3 голосов
/ 26 апреля 2011

Основная проблема здесь не в коротком замыкании.

Когда SQL Server компилирует пакет

declare @customerId int

set @customerId = null
select * from customer where ( (@customerId Is Null) Or CustomerId=@customerId)

Он не выполняет никакого "перехвата переменных", который учитываетпредыдущий оператор присваивания обрабатывает значение @customerId как неизвестное.

Если вы используете (некоторые версии) SQL Server 2008, вы можете использовать OPTION(RECOMPILE), чтобы заставить его перекомпилировать оператор после присвоения переменной.

Я предлагаю просмотреть ДинамическийУсловия поиска в T-SQL

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