Найти все ошибки внешнего ключа с помощью Oracle SET, ОСТАВЛЯЮЩЕГО ВСЕ ОТЛОЖЕННЫЕ - PullRequest
4 голосов
/ 10 ноября 2008

Я использую:

set constraints all deferred;
(lots of deletes and inserts)
commit;

Это работает как ожидалось. Если есть какие-либо нарушенные отношения, то фиксация завершается неудачно, и возникает ошибка, в которой перечисляется ОДИН из тех FK, на которых она терпит неудачу.

Пользователь исправляет оскорбительные данные и запускается снова. затем затрагивает другую проблему FK и повторяет процесс.

Что мне действительно нужно, так это список ВСЕХ FK за один раз, что приведет к сбою фиксации.

Конечно, я могу написать что-нибудь, чтобы проверить каждое отношение FK с помощью оператора select (один выбор на FK), но прелесть использования отложенного сеанса в том, что это все обрабатывается для меня.

Ответы [ 3 ]

2 голосов
/ 14 ноября 2008

Заданный немедленный ответ отлично сработал для меня.

Взяв пример A, B, C из другого поста:

SQL> create table a (id number primary key);

Table created.

SQL> create table b (id number primary key, a_id number, constraint fk_b_to_a foreign key (a_id) references a deferrable initially immediate);

Table created.

SQL> create table c (id number primary key, b_id number, constraint fk_c_to_b foreign key (b_id) references b deferrable initially immediate);

Table created.

SQL> insert into a values (1);

1 row created.

SQL> insert into b values (1,1);

1 row created.

SQL> insert into c values (1,1);

1 row created.

SQL> commit;

Commit complete.

У меня есть согласованный набор данных ... моя отправная точка. Теперь я начинаю сеанс для обновления некоторых данных - это то, что я пытался описать в своем посте.

SQL> set constraints all deferred;

Constraint set.

SQL> delete from a;

1 row deleted.

SQL> delete from b;

1 row deleted.

SQL> insert into b values (10,10);

1 row created.

SQL> set constraint fk_b_to_a immediate;
set constraint fk_b_to_a immediate
*
ERROR at line 1:
ORA-02291: integrity constraint (GW.FK_B_TO_A) violated - parent key not foun


SQL> set constraint fk_c_to_b immediate;
set constraint fk_c_to_b immediate
*
ERROR at line 1:
ORA-02291: integrity constraint (GW.FK_C_TO_B) violated - parent key not foun

Что говорит мне о нарушении ограничений (от C до B) и (от B до A) без отката транзакции. Что именно то, что я хотел.

Спасибо

1 голос
/ 11 ноября 2008

Первый вариант, вы можете посмотреть Журнал ошибок DML . Таким образом, вы оставляете свои ограничения активными, а затем выполняете вставки, а строки с ошибками переходят в таблицы ошибок. Вы можете найти их там, исправить их, заново вставить строки и удалить их из таблицы ошибок.

Второй вариант - вместо попытки фиксации - попытаться динамически повторно включить каждое отложенное ограничение, отлавливая ошибки. Вы бы посмотрели на процедуру PL / SQL, которая запрашивает у ALL_CONSTRAINTS наличие отложенных, а затем выполняет EXECUTE IMMEDIATE, чтобы сделать это ограничение незамедлительным. Этот последний бит будет в блоке с обработчиком исключений, чтобы вы могли отследить те, которые не сработали, но продолжили работу.

Лично я бы выбрал вариант (1), так как вы получаете отдельные записи, которые дают сбой, плюс вам не нужно беспокоиться об отложенных ограничениях и помните, чтобы сделать их немедленно после этого сценария, чтобы он сломать что-нибудь позже.

Я предполагаю, что где-то в памяти Oracle должен поддерживать список, по крайней мере, ограничений, которые потерпели неудачу, если не фактические строки. Я уверен, что во время коммита он не сканирует весь набор таблиц, чтобы проверить все ограничения.

1 голос
/ 10 ноября 2008

Механизм ошибок Oracle слишком примитивен, чтобы возвращать набор всех ошибок, которые МОГУТ произойти. Я имею в виду, это крутая мысль, но подумайте, что бы вы сделали, если бы написали код. Ваша стандартная обработка ошибок должна быть сорвана. Вместо того, чтобы возвращать ошибку, как только вы столкнетесь с ней, вам нужно как-то продолжить, чтобы посмотреть, сможете ли вы продолжить, если первая обнаруженная ошибка не была ошибкой вообще. И даже если бы вы сделали все это, вы все равно могли бы столкнуться с вероятностью того, что строка, добавленная вами, которая исправляет первую ошибку, фактически вызывает вторую ошибку.

Например:

A является родителем B, является родителем C. Я откладываю и вставляю C. Я получаю сообщение об ошибке, что родительской записи B нет. Я откладываю и добавляю B. Теперь я получаю еще одну ошибку, что нет A.

Это, конечно, возможно, и заранее сказать невозможно.

Я думаю, вы ищете сервер для выполнения работы, которая действительно является вашей обязанностью. С риском модификации -1 вы используете технику для стрельбы из автоматического оружия под названием «Распыли и молись» - стреляйте как можно больше раундов и надеетесь, что вы убьете цель. Такой подход просто не может работать здесь. Вы отключаете свой RI и делаете кучу шагов и надеетесь, что все RI сработают в конце, когда база данных "оценивает" ваш DML.

Я думаю, вы должны написать код.

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