Еще раз о таблице DUAL
Еще раз о таблице DUAL
8 мая 2001 г.
И.Гершанов с комментарием А.Бачина
Наш читатель Илья Гершанов написал в редакцию:
В недавней апрельской статье "Предупреждение проблем с таблицей DUAL", раздел "Опыт пользователей", написано, что если в таблице DUAL может оказаться более одной строки или не оказаться строк вовсе, то могут возникнуть проблемы.
Однако, буквально несколько дней назад в учебнике "Введение в Oracle SQL и PL/SQL" (410010RU11) на стр. 3-16 я прочел легко запоминающееся, просто афористичное определение таблицы DUAL: "DUAL - это фиктивная таблица, используемая для просмотра SYSDATE". Лучше не скажешь K .
Но, раз таблица фиктивная, то у нее нет сегмента, то и речи быть не может о добавлении строк. Был проведен эксперимент:
1. Запуск экземпляра в режиме "startup nomount" и запрос:
SVRMGR> select * from dual;
ADDR INDX INST_ID D
-------- ---------- ---------- -
00A18650 0 1 X
1 row selected.
2. Перевод экземпляра в режим "alter database mount;" и запрос
SVRMGR> select * from dual;
ADDR INDX INST_ID D
-------- ---------- ---------- -
00A18650 0 1 X
1 row selected.
3. Перевод экземпляра в работоспособное состояние "alter database open;" и запрос
SVRMGR> select * from dual;
D
-
X
1 row selected.
То есть в пути от nomount к open табличка успела поменяться. Таким образом, SYS.DUAL - это, и фиктивная таблица, и нормальный сегмент типа "TABLE" (Что и показывает запрос, например, к DBA_SEGMENTS).
Продолжим эксперименты с DML на таблице DUAL
4. Выполним следующие запросы в SQL*Plus. (Проверено на Oracle 8.0.6 и 8.1.7.)
SQL> select * from dual;
D
-
X
SQL> insert into dual values ('Y');
1 строка создана.
SQL> select * from dual;
D
-
X
SQL> delete from dual;
1 строка удалена.
SQL> select * from dual;
D
-
Y
SQL> delete from dual;
1 строка удалена.
SQL> select * from dual;
строки не выбраны
SQL> rollback;
Откат завершен.
Таким образом, SQL*Plus ограничивает все DML для DUAL по псевдостолбцу "...WHERE ROWNUM = 1...".
Комментарий А.Бачина: Скажем спасибо Илье Гершанову за интересный эксперимент. Немного его продолжим и покажем, что именно механизм SQL*Plus ограничивает выборку одной строкой.
SVRMGR> insert into dual values ('V');
1 row created.
SVRMGR> insert into dual values ('W');
1 row created.
SVRMGR> insert into dual values ('Y');
1 row created.
SVRMGR> select * from dual;
D
-
Y
V
W
X
4 rows selected.
И так далее. Но SQL*Plus верен себе
SQL> select * from dual;
D
-
Y
Хотя:
SQL> select count(*) from dual;
COUNT(*)
----------
4
и
SQL> select dummy from dual where dummy = 'W' ;
D
-
W
SQL> delete from dual where dummy in ('Y','V','W');
1 row deleted.
SQL> select * from dual;
D
-
V
Следовательно, в "недооткрытом" состоянии работает фиксированная (И.Гершанов неправильно называет ее фиктивной) таблица DUAL, вмонтирования в ядро Oracle.
После открытия базы начинает работать обычная (но специализированная) таблица словаря данных DUAL, про которую (скорее всего) только SQL*Plus "знает", что в ней только одно значение. Другие программные механизмы могут этого не знать, НО все пользуются однозначностью таблицы DUAL. Поэтому, если эта однозначность по каким-то причинам нарушена, то у многих приложений может "поехать крыша", со всеми вытекающими для пользователя результатами.
Поэтому АБД должен, как дворник (я не шучу), следить за чистотой вверенного ему пространства. Хорошо еще, что хоть не всякий scott/tiger сможет совершить такую диверсию.
SQL> connect scott/tiger
Connected.
SQL> insert into sys.dual values ('A')
nsert into sys.dual values ('A')
*
ERROR at line 1:
ORA-01031: insufficient privileges
|