22 февраля 2011 г.

oracle: NULL

Поле со значением NULL никогда не будет равно полю с тем же значением

Чтобы найти значения NULL можно использовать разные подходы:


1. Использовать ф-цию NVL(exp1,exp2)
если exp1 = NULL, то ф-ция возвращает exp2


Примечание: NVL для своей работы требует вычислить значения всех аргументов, это надо учитывать при оптимизации запроса. Если нужно вычислить только 1й NULL эелемент, то лучше использовать ф-цию DECODE, которая вычисляет выражение по мере надобности

Например,

SQL> create table my_table (a int, b int);
SQL> insert into my_table values (1, 1) ;
SQL> insert into my_table values (1, NULL);
SQL> insert into my_table values (NULL, 1) ;
SQL> insert into my_table values (NULL, NULL);
SQL> insert into my_table values (NULL, NULL);
SQL> insert into my_table values (NULL, NULL);
SQL> insert into my_table values (NULL, NULL);

-- этот запрос не вернёт строки, где NULL=NULL
SQL> select rownum,a,b from my_table where a=b;

ROWNUM    A              B
---------- ---------- ----------
1                    1               1

-- это вернёт NULL=NULL
SQL> select rownum,a,b from my_table WHERE NVL (a, 0) = NVL (b, 0);

2. Использовать ф-цию DECODE


DECODE compares expr to each search value one by one. If expr is equal to a search, then Oracle Database returns the corresponding result. If no match is found, then Oracle returns default. If default is omitted, then Oracle returns null.

DECODE вычисляет выражение по мере надобности

-- это вернёт NULL=NULL
SQL> select rownum,a,b  from my_table  WHERE DECODE (a, b, 'YES', 'NO') = 'YES';

3. Использовать проверку IS NULL

 -- это вернёт NULL=NULL
SQL> select rownum,a,b  from my_table  WHERE (a = b OR (a IS NULL AND b IS NULL));

4. Использовать недокументированную ф-цию sys_op_map_nonnull()

This function has been around for a while, but is still undocumented as of the latest Oracle database release (10gR2). Being undocumented means that it should not be used in production code

-- это вернёт NULL=NULL
SQL> select rownum,a,b  from my_table WHERE sys_op_map_nonnull(a) = sys_op_map_nonnull(b);