Флаги Трассировки ! "1204" было неоценимо в отладке мертвой блокировки на SQL Server 2000 (2005 имеет лучшие инструменты для этого).
В зависимости от типа данных и возможных значений для столбцов:
COALESCE(A, -1) <> COALESCE(B, -1)
Уловка находит значение (здесь я использовал -1), которое НИКОГДА не будет отображаться в ваших данных.
Другой способ:
(A <> B) OR (A IS NOT NULL AND B IS NULL) OR (A IS NULL AND B IS NOT NULL)
Это может быть проблемой в зависимости от того, как ваша конкретная СУБД обрабатывает NULL. По стандарту ANSI это должно дать вам то, что вы хотите, но кто все равно следует стандартам. :)
PS - Я также должен указать, что использование функции COALESCE может сделать недействительным использование индексов при сравнении столбцов. Проверьте свой план запроса и производительность запроса, чтобы увидеть, не проблема.
PPS - Я только что заметил, что OMG Ponies упомянул, что Informix не поддерживает COALESCE. Я считаю, что это стандартная функция ANSI, но посмотрите, что я сказал выше о стандартах ...
Проверьте свой план запроса и его производительность, чтобы убедиться, что это проблема.PPS - Я только что заметил, что OMG Ponies упомянул, что Informix не поддерживает COALESCE. Я считаю, что это стандартная функция ANSI, но посмотрите, что я сказал выше о стандартах ...
Проверьте свой план запроса и его производительность, чтобы убедиться, что это проблема.PPS - Я только что заметил, что OMG Ponies упомянул, что Informix не поддерживает COALESCE. Я считаю, что это стандартная функция ANSI, но посмотрите, что я сказал выше о стандартах ...
Я бы лично выписал выражение, которое вы придумали, особенно если ожидается рост таблицы. Заключение столбцов в вызовы функций снижает производительность, так как механизм не может использовать какие-либо индексы, которые у вас есть для этих столбцов. Конечно, в маленькой таблице это может не быть проблемой, но я все же предпочитаю делать это явным образом на тот случай, если таблица в конце концов вырастет.
вы можете попробовать что-то подобное в informix?
CASE
WHEN a IS NULL AND B IS NULL THEN false
WHEN a IS NULL OR B IS NULL THEN true
ELSE a <> B
END
IBM Informix Dynamic Server имеет несколько своеобразный взгляд на логические значения по ряду исторических (так называемых «плохих») причин. Адаптируя идею, предложенную @astander, это выражение CASE «работает», но я бы первым сказал «не очевидно» (видите, я сказал это раньше, чем вы!). Этап настройки:
create table x(a int, b int);
insert into x values(null, null);
insert into x values(null, 1);
insert into x values(1, null);
insert into x values(1, 1);
insert into x values(1, 2);
Оператор SELECT:
SELECT *
FROM x
WHERE CASE
WHEN a IS NULL AND b IS NULL THEN 'f'::BOOLEAN
WHEN a IS NULL OR b IS NULL THEN 't'::BOOLEAN
WHEN a != b THEN 't'::BOOLEAN
ELSE 'f'::BOOLEAN
END
;
Результат этого запроса:
1
1
1 2
Проблемы:
Да, мне очень больно говорить об этом.
Проблема в том, что a <> b
(или a = b
) дает NULL
, а не 1
или 0
, когда один или оба операнда имеют значение NULL. Это не имеет значения для случая =
, потому что NULL OR 1
равно 1
, а NULL OR 0
равно NULL
], который ведет себя как 0
для выбора в предложении WHERE
.
Вы можете сказать:
a<>b OR (a IS NULL)<>(b IS NULL)
Однако необходимость сделать это в любом случае может быть признаком того, что вы неправильно используете NULL и следует рассмотреть возможность изменения схемы, чтобы использовать другое значение NOT NULL для обозначения этого сопоставимого условия.
Например, если у вас есть таблица person
с столбцом title
, не используйте NULL, чтобы указать, что у них нет заголовка; это не «недостающие» данные, просто не существует названия. Так что сохраните его как пустую строку ''
, которую вы можете с удовольствием сравнить с другими пустыми строками. (Ну, если, конечно, вы не запустите Oracle, с его проблемой пустой строки ...)
Для SQL Server используйте:
WHERE ISNULL(A, '') <> ISNULL(B, '')
Если вы хотите быть уверенным в том, как обрабатываются NULL, вам придется использовать все, что поддерживает Informix для проверки NULL. Я нечасто появлялся, кроме версии SE не поддерживает COALESCE, но она поддерживает DECODE и, возможно, CASE.
WHERE COALESCE(t.a, 0) != COALESCE(t.b, 0)
WHERE DECODE(NULL, 0, t.a) != DECODE(NULL, 0, t.b)