тестирование неравенства со столбцами, которые могут быть пустыми

Флаги Трассировки ! "1204" было неоценимо в отладке мертвой блокировки на SQL Server 2000 (2005 имеет лучшие инструменты для этого).

12
задан Community 23 May 2017 в 12:15
поделиться

7 ответов

В зависимости от типа данных и возможных значений для столбцов:

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, но посмотрите, что я сказал выше о стандартах ...

10
ответ дан 2 December 2019 в 21:03
поделиться

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

3
ответ дан 2 December 2019 в 21:03
поделиться

вы можете попробовать что-то подобное в 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 Guide to SQL: Syntax, CASE Expressions

1
ответ дан 2 December 2019 в 21:03
поделиться

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

Проблемы:

  • IDS не распознает FALSE, TRUE или UNKNOWN в качестве ключевых слов.
  • IDS не распознает логические выражения например, 'a! = b' (или 'a <> b') как таковое.

Да, мне очень больно говорить об этом.

0
ответ дан 2 December 2019 в 21:03
поделиться

Проблема в том, что 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, с его проблемой пустой строки ...)

0
ответ дан 2 December 2019 в 21:03
поделиться

Для SQL Server используйте:

WHERE ISNULL(A, '') <> ISNULL(B, '')
0
ответ дан 2 December 2019 в 21:03
поделиться

Если вы хотите быть уверенным в том, как обрабатываются 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)
0
ответ дан 2 December 2019 в 21:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: