Спрятать колонку

Oracle и NULL

Одним из небольших подводных камней в Oracle может является Null и операции с ним.
Для работы с ним нужно четко уяснить два правила:
1. Null <> Null всегда и везде
2. Помнить о преобразовании типов.

Рассмотрим далее пример.

Создадим таблицу:

CREATE TABLE test_null(
  v_is_null varchar2(10)
);

прогоним скрипт:

INSERT INTO test_null(v_is_null) VALUES(NULL);
INSERT INTO test_null(v_is_null) VALUES('  ');
INSERT INTO test_null(v_is_null) VALUES('');

сколько строк вернут следующие запросы?
1.

SELECT  * FROM test_null
WHERE v_is_null = NULL

2.

SELECT  * FROM test_null
WHERE v_is_null = ''

3.

SELECT  * FROM test_null
WHERE v_is_null = '  '

Правильные ответы:
1. ноль строк. Потому что Null <> Null
2. ноль строк. Потому что '' (пустая строка) всегда трактуется как Null, далее смотрите пункт 1)
3. одна строка.

Помните о преобразованиях типов.

Oracle. Индексы и Null

Вопросы, связанные с NULL значениями, весьма интересны в oracle. Пока не столкнешься на практике - не узнаешь, в чем подвох с ними.

Возьмем известный и проверяемый факт: индексы не хранят null значения. Что дает нам это на практике?
Рассмотрим следующую ситуацию. Возможно, что этот пример можно считать просто наглядным, однако, он покажет, насколько важно знать на этапе проектирования, какие запросы будут идти к таблице.

Есть таблица, в которой лежат и "основные данные" и те, для которых необходима "предобработка". Чтобы не плодить сущностей, решили вместо PK сделать UK и необработанные записи хранить в таблице со значением NULL. Казалось бы, проблемы нет.

Приведу пример:

Создадим таблицу с уникальным ключом по полю, заполним ее данными, а в конце соберем статистику по индексу.

CREATE TABLE select_null(
  id number
);
 
CREATE UNIQUE INDEX X_ID_SELECT_NULL ON select_null(id);
 
INSERT INTO select_null(id) VALUES(1);
INSERT INTO select_null(id) VALUES(2);
INSERT INTO select_null(id) VALUES(NULL);
INSERT INTO select_null(id) VALUES(NULL);
INSERT INTO select_null(id) VALUES(NULL);
INSERT INTO select_null(id) VALUES(3);
 
commit;
 
ANALYZE INDEX X_ID_SELECT_NULL COMPUTE STATISTICS;

Теперь перед нами стоит тривиальная задача: вычитать все данные, которые нуждаются в предобработке, т.е. где id = NULL. Это очень просто:

SELECT * FROM select_null
WHERE id IS NULL

Ура, мы справились. Или же нет? Взглянем на план выполнения запроса:

SELECT STATEMENT  ALL_ROWSCost: 3  Bytes: 39  Cardinality: 3  	
	1 TABLE ACCESS FULL TABLE USR.SELECT_NULL Cost: 3  Bytes: 39  Cardinality: 3  

Да в ней же есть FULL SCAN. Откуда взялся он!? Ответ прост: как мы знаем, в индексе не содержаться NULL значения. Индекс будет проигнорирован и не помогут тут ни хинты, ни RBO.

>> Читать далее
RSS-материал

Наверх