Подтвердить что ты не робот

Получить null == null в SQL

Я хочу искать таблицу базы данных в столбце с нулевым значением. Иногда значение, которое я ищу, само по себе является NULL. Поскольку Null равно ничто, даже NULL, говоря

where MYCOLUMN=SEARCHVALUE 

не удастся. Прямо сейчас я должен прибегнуть к

where ((MYCOLUMN=SEARCHVALUE) OR (MYCOLUMN is NULL and SEARCHVALUE is NULL))

Есть ли более простой способ сказать это?

(Я использую Oracle, если это имеет значение)

4b9b3361

Ответ 1

Вы можете делать вещи IsNull или NVL, но это просто заставит двигатель сделать больше работы. Вы будете вызывать функции для преобразования столбцов, которые затем должны сравнивать результаты.

Используйте то, что у вас есть

where ((MYCOLUMN=SEARCHVALUE) OR (MYCOLUMN is NULL and SEARCHVALUE is NULL))

Ответ 2

@Энди Лестер утверждает, что исходная форма запроса более эффективна, чем использование NVL. Я решил проверить это утверждение:

    SQL> DECLARE
      2    CURSOR B IS
      3       SELECT batch_id, equipment_id
      4         FROM batch;
      5    v_t1  NUMBER;
      6    v_t2  NUMBER;
      7    v_c1  NUMBER;
      8    v_c2  NUMBER;
      9    v_b   INTEGER;
     10  BEGIN
     11  -- Form 1 of the where clause
     12    v_t1 := dbms_utility.get_time;
     13    v_c1 := dbms_utility.get_cpu_time;
     14    FOR R IN B LOOP
     15       SELECT COUNT(*)
     16         INTO v_b
     17         FROM batch
     18        WHERE equipment_id = R.equipment_id OR (equipment_id IS NULL AND R.equipment_id IS NULL);
     19    END LOOP;
     20    v_t2 := dbms_utility.get_time;
     21    v_c2 := dbms_utility.get_cpu_time;
     22    dbms_output.put_line('For clause: WHERE equipment_id = R.equipment_id OR (equipment_id IS NULL AND R.equipment_id IS NULL)');
     23    dbms_output.put_line('CPU seconds used: '||(v_c2 - v_c1)/100);
     24    dbms_output.put_line('Elapsed time: '||(v_t2 - v_t1)/100);
     25  
     26  -- Form 2 of the where clause
     27    v_t1 := dbms_utility.get_time;
     28    v_c1 := dbms_utility.get_cpu_time;
     29    FOR R IN B LOOP
     30       SELECT COUNT(*)
     31         INTO v_b
     32         FROM batch
     33        WHERE NVL(equipment_id,'xxxx') = NVL(R.equipment_id,'xxxx');
     34    END LOOP;
     35    v_t2 := dbms_utility.get_time;
     36    v_c2 := dbms_utility.get_cpu_time;
     37    dbms_output.put_line('For clause: WHERE NVL(equipment_id,''xxxx'') = NVL(R.equipment_id,''xxxx'')');
     38    dbms_output.put_line('CPU seconds used: '||(v_c2 - v_c1)/100);
     39    dbms_output.put_line('Elapsed time: '||(v_t2 - v_t1)/100);
     40  END;
     41  /


    For clause: WHERE equipment_id = R.equipment_id OR (equipment_id IS NULL AND R.equipment_id IS NULL)
    CPU seconds used: 84.69
    Elapsed time: 84.8
    For clause: WHERE NVL(equipment_id,'xxxx') = NVL(R.equipment_id,'xxxx')
    CPU seconds used: 124
    Elapsed time: 124.01

    PL/SQL procedure successfully completed

    SQL> select count(*) from batch;

  COUNT(*)
----------
     20903

SQL> 

Я был удивлен, узнав, насколько правдивый Энди. Это почти на 50% больше, чем решение NVL. Таким образом, хотя один фрагмент кода может выглядеть не таким аккуратным или элегантным, как другой, он может быть значительно более эффективным. Я выполнял эту процедуру несколько раз, и результаты были почти одинаковы каждый раз. Престижность Энди...

Ответ 4

Я не знаю, проще ли это, но я иногда использовал


WHERE ISNULL(MyColumn, -1) = ISNULL(SearchValue, -1)

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

ПРИМЕЧАНИЕ. Я использую MS SQL, а не Oracle, поэтому не уверен, что допустимо "ISNULL".

Ответ 5

Используйте NVL для замены null с помощью некоторого фиктивного значения с обеих сторон, например:

WHERE NVL(MYCOLUMN,0) = NVL(SEARCHVALUE,0)

Ответ 6

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

Далее следует псевдокод.

if (SEARCHVALUE IS NULL) {
    condition = 'MYCOLUMN IS NULL'
} else {
    condition = 'MYCOLUMN=SEARCHVALUE'
}
runQuery(query,condition)

Ответ 7

Если возможно внеполосное значение:

where coalesce(mycolumn, 'out-of-band') 
    = coalesce(searchvalue, 'out-of-band')

Ответ 8

Попробуйте

WHERE NVL(mycolumn,'NULL') = NVL(searchvalue,'NULL')

Ответ 9

Это также может выполнять работу в Oracle.

WHERE MYCOLUMN || 'X'  = SEARCHVALUE || 'X'

Есть некоторые ситуации, когда он превосходит тест IS NULL с помощью OR.

Я также был удивлен, что DECODE позволяет вам проверять NULL на NULL.

WITH 
TEST AS
(
    SELECT NULL A FROM DUAL
)
SELECT DECODE (A, NULL, 'NULL IS EQUAL', 'NULL IS NOT EQUAL')
FROM TEST

Ответ 10

Это ситуация, в которой мы находимся во многом с нашими функциями Oracle, которые управляют отчетами. Мы хотим разрешить пользователям вводить значение для ограничения результатов или оставить его пустым, чтобы вернуть все записи. Это то, что я использовал, и это хорошо сработало для нас.

WHERE rte_pending.ltr_rte_id = prte_id
  OR ((rte_pending.ltr_rte_id IS NULL OR rte_pending.ltr_rte_id IS NOT NULL)
      AND prte_id IS NULL)

Ответ 11

Я думаю, что у вас все в порядке. Вы могли бы использовать:

where NVL(MYCOLUMN, '') = NVL(SEARCHVALUE, '')