Саргативные запросы с использованием ISNULL в TSQL

Я хочу предотвратить использование выражений, не подлежащих анализу, в моих запросах, как лучше проверить нулевое условие?

AND c.Account IS NOT NULL 
AND c.Account <> ''

or

AND ISNULL(c.Account,'') <> ''

Мне пришло в голову указать, что Account исходит из LEFT JOIN, поэтому оно может быть нулевым. Мне нужны случаи, когда они только пересекаются, что означает, что я должен просто использовать INNER JOIN, да? Спасибо за фейспалмы ;)

Однако, не обращая внимания на это тошнотворное самоосознание, я все же хочу знать ответ на этот вопрос в общем случае, когда я не могу сделать Account столбцом NOT NULL.


person jcolebrand    schedule 17.02.2011    source источник
comment
Лучше установить поле Account как NOT NULL, так как эти значения означают одно и то же для вас, и лучше использовать COALESCE, потому что это часть стандарта SQL.   -  person LukLed    schedule 17.02.2011
comment
пустая строка, эквивалентная NULL? Ээээээ!   -  person Mitch Wheat    schedule 17.02.2011
comment
@lukled ~ Итак, где лучше использовать COALESCE?   -  person jcolebrand    schedule 17.02.2011
comment
@Mitch Wheat: Что не так с пустой строкой, эквивалентной NULL?   -  person LukLed    schedule 17.02.2011
comment
@drachenstern: Нет. COALESCE просто универсален, работает с любой базой данных. Это ничего не значит с точки зрения производительности.   -  person LukLed    schedule 17.02.2011
comment
И мой совет — используйте первую версию, потому что вторая, вероятно, может убить использование индекса в более старой версии SQL Server.   -  person LukLed    schedule 17.02.2011
comment
@Lukled: NULL не является значением. Нуль считается неизвестным или отсутствующим. Пустая строка означает, что вы ее знаете, и она пуста.   -  person Mitch Wheat    schedule 17.02.2011
comment
@Mitch Wheat: Скажи это инженерам Oracle :) В Oracle пустая строка равна нулю.   -  person LukLed    schedule 17.02.2011
comment
@lukled Я все же пометил вопрос как Sql-Server для начала;)   -  person jcolebrand    schedule 17.02.2011
comment
@drachenstern: Да. Я дал свой ответ по поводу вашего SQL и сказал, что первый для меня безопаснее. И тогда я утверждал, что NULL — это другое значение, чем пустая строка.   -  person LukLed    schedule 17.02.2011
comment
@lukled Просто чтобы все было ясно ;)   -  person jcolebrand    schedule 17.02.2011
comment
@LukLed: COALESCE заметно медленнее в SQL Server из-за обработки типов данных.   -  person gbn    schedule 17.02.2011
comment
@gbn: Что вы подразумеваете под демонстративно? Это действительно видно?   -  person LukLed    schedule 17.02.2011
comment
@LukLed: да. один пример sqlblog.com/blogs/ adam_machanic/archive/2006/07/12/ . Даже если это незначительное сравнение, COALESCE может иметь побочные эффекты. ISNULL принимает тип данных первого аргумента, COALESCE принимает тип данных с наивысшим приоритетом. Итак, WHERE smallintcol = COALESCE (@smallintvalue, @intvaue) означает преобразование smallintcol в int...   -  person gbn    schedule 17.02.2011
comment
@gbn: я скопировал код из этого теста и запустил его на SQL Server 2008. COALESCE был намного быстрее в (строка, строка) и имел такую ​​​​же производительность в (ноль, строка). С другой стороны, в (int, int) ISNULL был быстрее, но разница была намного меньше, чем (string, string). Так что я бы не сказал, что ISNULL лучше. По-разному.   -  person LukLed    schedule 17.02.2011
comment
@gbn Как вы думаете, мне следовало опубликовать это на dba.SE?   -  person jcolebrand    schedule 17.02.2011
comment
@drachenstern: в любом месте, правда. здесь вы получите больше просмотров   -  person gbn    schedule 17.02.2011
comment
@gbn Да, я не думал, что это действительно уровень ниндзя, поэтому не был уверен :\   -  person jcolebrand    schedule 17.02.2011
comment
Что ты спрашиваешь? IS NOT NULL или НЕ NULL И НЕ ПУСТАЯ СТРОКА?   -  person Martin Smith    schedule 11.09.2015
comment
@MartinSmith имеет ли это поле значение, которое не является пустой строкой   -  person jcolebrand    schedule 12.09.2015


Ответы (3)


C.Account <> '' эквивалентно ISNULL( c.Account, '' ) <> ''

SQL Server, вероятно, достаточно умен, чтобы преобразовать IsNull в эквивалентное выражение SARG, но если вы склонны использовать функцию, Coalesce — лучший выбор, поскольку он является частью стандарта SQL, допускает несколько значений (вместо двух с IsNull). ) и избегает использования, пожалуй, самого запутанного имени функции, когда-либо придуманного Microsoft в IsNull.

person Thomas    schedule 17.02.2011
comment
Как вы думаете, почему SQL-Server достаточно умен, чтобы преобразовать его в выражение, доступное для анализа? Насколько мне известно ISNULL/COALESCE не подлежат sargable и должны быть заменены с IS NULL OR <> ''. Кроме того, COALESCE все еще имеет серьезную ошибку в sql-сервере, поэтому ISNULL следует предпочесть, пока вам не понадобится COLESCE. Он переводится в CASE, который оценивается дважды. connect.microsoft.com/SQLServer/ обратная связь/детали/336002/ - person Tim Schmelter; 17.12.2013
comment
@TimSchmelter - RE: IsNull, IMO, никогда не следует использовать IsNull. Нет никакого оправдания. Помимо того факта, что это единственная функция с самым ужасным названием из когда-либо созданных, она не соответствует стандарту ANSI, а обстоятельство, которое вы отметили, возникло пять лет назад и применимо только при использовании подзапроса (так что это может быть исправлено). Лучше записать это как оператор case, чем использовать IsNull. Я бы хотел, чтобы MS полностью отказалась от этого. Что касается возможности анализа, я сказал, что MS может быть достаточно умной, чтобы сделать это, поскольку она преобразует функцию в выражение case, но есть вероятность, что синтаксический анализатор не справится с этим. - person Thomas; 17.12.2013
comment
статус ошибки все еще активен. Я все еще на SQL-Server 2005, и, по крайней мере, там нет исправлений. Этот запрос возвращает два сообщения об ошибках вместо одного (как в случае с ISNULL): SELECT COALESCE(xyz, 0) FROM sys.objects. Большинство людей не знают об этом, но все рекомендуют использовать COALESCE вместо ISNULL. Даже без подзапросов ISNULL требует на 20-30% меньше ресурсов процессора. - person Tim Schmelter; 17.12.2013
comment
На самом деле IsNull был передан Microsoft от Sybase. Возможно, это самое запутанное название функции среди всех продуктов, приобретенных Microsoft. - person John Zabroski; 22.12.2018

Просто используйте WHERE c.Account <> ''

Это не оценивается как истинное ни для null, ни для пустой строки и потенциально может быть оценено с использованием поиска диапазона для Account.

Использование ISNULL или COALESCE сделало бы выражение недоступным для анализа и в любом случае не требуется.

Если вы хотите отличить действительно пустые строки от строк, полностью состоящих из пробелов, вы можете использовать

 WHERE c.Account IS NOT NULL AND DATALENGTH(c.Account) > 0

Который сочетает в себе один предикат с возможностью анализа, который позволяет поиску по индексу пропускать нули в индексе с предикатом без возможности анализа по сравнению с остальными значениями.

person Martin Smith    schedule 11.09.2015

COALESCE IS SARGABLE, поскольку это всего лишь сокращенное выражение (эквивалентно использованию CASE WHEN IS NOT NULL THEN ELSE...).

ISNULL — это встроенная функция, поэтому ISNULL НЕ ДОПУСКАЕТСЯ SARGABLE.

person IGNACE Bruno    schedule 10.09.2015