Базы данных Oracle - статьи

         

Проблема с каскадным удалением


Вопрос. Допустим, у меня есть две таблицы, T1 (родительская) и T2 (дочерняя), которая связана с родительской таблицей внешним ключом с предложением каскадного удаления: REFERENCES T1(X,Y,Z...) ON DELETE CASCADE. Строки могут удаляться из таблицы T1, в этом случае из таблицы T2 также удаляются дочерние строки. Точно так же строки могут удаляться непосредственно из таблицы T2, но без соответствующего удаления родительских строк из таблицы T1.

Я хочу предотвратить возникновение второй ситуации. То есть, я хочу гарантировать, что выполняются только удаления из родительской таблицы (в результате которых удаляются и дочерние записи), а отдельные удаления из дочерней таблицы не выполняются. Проблема заключается в том, что сначала всегда выполняются удаления из дочерней таблицы, а затем – из родительской. Так, если я пытаюсь добиться этого с помощью триггера на дочерней таблице, но это не помогает, поскольку во время выполнения операции удаления из дочерней таблицы, нет никакого способа узнать, будет ли затем следовать удаление из родительской таблицы. Я предпочел бы простое решение (их, наверное, много), потому что экзотические, нестандартные решения могут оказаться у нас нереализуемыми.



Следующие шаги:


Том Кайт, вице-президент корпорации Oracle, отвечает на наиболее трудные вопросы, связанные с технологией баз данных Oracle. Наиболее яркие материалы этого форума публикуются в данной колонке.
ЧИТАЙТЕ более подробно о

совместном использовании курсоров

Oracle Database Performance Tuning Guide

аналитических функциях

Oracle Database SQL Reference ЧИТАЙТЕ еще Тома

Expert Oracle: 9i and 10g Programming Techniques and Solutions

Ответ. Для меня это просто защита данных. Вы не хотите удалять строки непосредственно из дочерней таблицы, следовательно, никому не предоставляйте объектную привилегию DELETE на эту таблицу. Это можно сделать легко: SQL> create table p 2 ( x int primary key ); Table created.

SQL> create table c 2 ( x references p 3 on delete cascade ); Table created.


SQL> insert into p 2 values ( 1 ); 1 row created.

SQL> insert into c 2 values ( 1 ); 1 row created.

SQL> grant select, delete 2 on p to scott; Grant succeeded.

SQL> grant select 2 on c to scott; Grant succeeded.



SQL> connect scott/tiger Connected.

SQL> delete from ops$tkyte.c; delete from ops$tkyte.c * ERROR at line 1: ORA-01031: insufficient privileges

SQL> delete from ops$tkyte.p; 1 row deleted.

SQL> select * from ops$tkyte.c; no rows selected

Вы можете сказать: "Да, но администратор базы данных может войти в систему и удалить эти строки...". Я же скажу: "Да, но администратор базы данных может обойти все что угодно, установленное вами, – все что угодно, ну и что"? Владелец схемы может сделать то же самое; поэтому вы просто защищаете данные, чтобы никто (на уровне приложений) не мог удалить их.

Есть ли способы сделать это с помощью триггеров? Да, но писать их довольно сложно (и их также можно обмануть).

Средства защиты делают это чисто.

Фактически, если вы использовали язык PL/SQL и никогда не предоставляли никаких объектных привилегий INSERT/UPDATE/DELETE, подумайте, насколько "безопасно" вы могли сделать это!

Ведущий данной колонки Том Кайт () работает в корпорации Oracle с 1993 года. Кайт – вице-президент Oracle, возглавляющий группу Oracle Public Sector, он автор книг "Expert Oracle: 9i and 10g Programming Techniques and Solutions" (Apress, 2005), "Effective Oracle by Design" (Oracle Press, 2003) и "Expert One on One: Oracle" (Apress, 2003) ( Прим. пер. Имеется русский перевод: Oracle для профессионалов. Книга 1. Архитектура и основные особенности. Книга 2. Расширение возможностей и защита. – ДиаСофт.).


Содержание раздела