Использование столбцов, допускающих значение NULL, в предложении WHERE

Предположим, что определение таблицы в SQL Server выглядит следующим образом:

CREATE TABLE MyTable (
  Id   UNIQUEIDENTIFIER NULL,
  Info VARCHAR(MAX)
)

И запрос:

DECLARE @id UNIQUEIDENTIFIER
DECLARE @info VARCHAR(MAX)
IF @id IS NOT NULL
BEGIN
  SELECT @info = Info
    FROM MyTable
    WHERE Id = @id
END

В этом случае статический анализатор кода Visual Studio выдает следующую ошибку:

Предупреждение : SR0007 : Microsoft.Performance : Столбцы, допускающие значение NULL, могут привести к тому, что окончательные результаты будут оцениваться как NULL для предиката.

Я не вижу здесь проблемы. Ошибка связана с производительностью; MSDN говорит, что я должен использовать ISNULL(), но сравнение равенства с NULL всегда ложно, верно? Я что-то упустил, или предупреждение просто неправильное?


person RickNZ    schedule 05.12.2009    source источник


Ответы (6)


Я думаю, что это относится к предложению WHERE. Это говорит о том, что и ваш параметр, и ваш столбец могут быть NULL, и в этом случае ваше предложение WHERE больше не оценивается как true/false. Направляя столбец, допускающий значение NULL, в тот, для которого всегда определено значение (через ISNULL), вы находитесь в лучшей форме с точки зрения логики.

Вот документация Microsoft по этой ошибке.

С другой стороны, NULL якобы делают запросы намного медленнее.

person Mark Canlas    schedule 05.12.2009
comment
Ага! Это когда они оба NULL, на что он пытается жаловаться - за исключением того, что если я исключаю это с помощью IF или более подробной информации в предложении WHERE, анализатор не улавливает этого. Я не уверен, что вы имеете в виду, когда NULL замедляет запросы. Вы имеете в виду, что столбец, допускающий значение NULL, работает медленнее, чем столбец, не допускающий значения NULL? Или вы про ISNULL? - person RickNZ; 05.12.2009
comment
Я утверждаю, что столбец, допускающий значение NULL, извлекается/обрабатывается медленнее, чем столбец, не допускающий значения NULL. Но мне нечем это подкрепить, так что принимайте это с недоверием. = Д - person Mark Canlas; 05.12.2009

Я думаю, что анализатор может просто не учитывать ваш оператор IF.

Ваш код кажется мне правильным.

person Adriaan Stander    schedule 05.12.2009
comment
Сообщение жалуется на столбец, допускающий значение NULL, а не на параметр, допускающий значение NULL. Кроме того, если я изменю предложение WHERE на: Id IS NOT NULL AND Id = @id или @id IS NOT NULL AND Id = @id, сообщение сохранится. - person RickNZ; 05.12.2009

Сравнение с нулевым значением зависит от настройки.

When SET ANSI_NULLS is ON, all comparisons against a null value evaluate to UNKNOWN

When SET ANSI_NULLS is ON, a SELECT statement that uses WHERE column_name = NULL returns zero rows even if there are null values in column_name. A SELECT statement that uses WHERE column_name <> NULL returns zero rows even if there are no nnull values in column_name.

When SET ANSI_NULLS is OFF, the Equals (=) and Not Equal To (<>) comparison operators do not follow the ISO standard.

Это отсюда.

person Damir Sudarevic    schedule 05.12.2009

Я думаю, что это ложное предупреждение - можете ли вы подавить его в каждом конкретном случае или полностью это конкретное предупреждение?

Что происходит, когда вы это делаете?:

CREATE TABLE MyTable (
  Id   UNIQUEIDENTIFIER NOT NULL,
  Info VARCHAR(MAX)
)
person Cade Roux    schedule 05.12.2009
comment
Изменение его на NOT NULL устраняет предупреждение. Я, вероятно, закончу тем, что подавлю сообщение; Я просто хочу сначала убедиться, что полностью понимаю, почему это происходит, и сообщить об этом, если это действительно ошибка. - person RickNZ; 06.12.2009

IF @id IS NOT NULL

следует заменить на

IF ISNull(@id, -1) <> -1
person Raj    schedule 05.12.2009
comment
@Raj Разве это не то же самое, что если @id не равен нулю? какой смысл его менять? - person dan; 05.12.2009
comment
Этот код на самом деле даже не скомпилируется, потому что @id — это GUID, а не INT. - person RickNZ; 05.12.2009
comment
ой, я думал, что id был целым числом, извините. - person Raj; 05.12.2009

@ Радж: "IF ISNull(@id, -1) ‹> -1"

Я бы не стал этого делать, поскольку он фактически заменяет запись в таблице.

person ram    schedule 05.12.2009
comment
но, к сожалению, я новичок и у меня недостаточно баллов (или репутации) для комментариев :( stackoverflow.com/faq - person ram; 05.12.2009