Определите пустой указатель Oracle == пустой указатель

Я хочу искать таблицу базы данных на nullable столбце. Иногда значение, я - поиск, является самостоятельно НУЛЕВЫМ. Так как Пустой указатель ничему не равен, даже ПУСТОЙ УКАЗАТЕЛЬ, говоря

where MYCOLUMN=SEARCHVALUE 

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

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

Существует ли более простой способ сказать это?

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

44
задан Marcus Leon 13 September 2019 в 15:05
поделиться

9 ответов

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

Использование, что Вы имеете

where ((MYCOLUMN=SEARCHVALUE) OR (MYCOLUMN is NULL and SEARCHVALUE is NULL))
68
ответ дан Andy Lester 26 November 2019 в 21:40
поделиться

Lester @Andy утверждает, что исходная форма запроса более эффективна, чем использование 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> 

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

36
ответ дан DCookie 26 November 2019 в 21:40
поделиться

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


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

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

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

13
ответ дан Marcus Leon 26 November 2019 в 21:40
поделиться

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

WHERE NVL(MYCOLUMN,0) = NVL(SEARCHVALUE,0)
7
ответ дан JosephStyons 26 November 2019 в 21:40
поделиться

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

Псевдокод следует.

if (SEARCHVALUE IS NULL) {
    condition = 'MYCOLUMN IS NULL'
} else {
    condition = 'MYCOLUMN=SEARCHVALUE'
}
runQuery(query,condition)
5
ответ дан Vinko Vrsalovic 26 November 2019 в 21:40
поделиться

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

where coalesce(mycolumn, 'out-of-band') 
    = coalesce(searchvalue, 'out-of-band')
2
ответ дан Ted 26 November 2019 в 21:40
поделиться

Это может также сделать задание в Oracle.

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

существуют некоторые ситуации, где это бьется, ПУСТОЙ тест с ИЛИ.

я был также удивлен, что ДЕКОДИРУЮТ, позволяет Вам проверить ПУСТОЙ УКАЗАТЕЛЬ по ПУСТОМУ УКАЗАТЕЛЮ.

WITH 
TEST AS
(
    SELECT NULL A FROM DUAL
)
SELECT DECODE (A, NULL, 'NULL IS EQUAL', 'NULL IS NOT EQUAL')
FROM TEST
1
ответ дан EvilTeach 26 November 2019 в 21:40
поделиться

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

where NVL(MYCOLUMN, '') = NVL(SEARCHVALUE, '')
0
ответ дан Carl 26 November 2019 в 21:40
поделиться

Попробуйте

WHERE NVL(mycolumn,'NULL') = NVL(searchvalue,'NULL')
1
ответ дан bluish 26 November 2019 в 21:40
поделиться
Другие вопросы по тегам:

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