оператор в блоке SQL выбрасывает ограничение целостности, но не как отдельный оператор - PullRequest
0 голосов
/ 11 января 2019

Я выполняю блок операторов удаления, которые следуют за зависимостями родителя / потомка. Когда блок выполняется, оператор выбрасывает ограничения целостности. Однако когда оператор (ы) выполняется / выполняется индивидуально, ошибок не возникает.

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

begin 
...
delete from rma_receipts where rma_detail_id in (select id from rma_detail where rma_id in (select id from rma where nvl(eplant_id, 1) in (1, 3)));
commit;
--constraint being triggered
delete from rma_detail where rma_id in (select id from rma where eplant_id in (1, 3));
... 
end;

не должно быть никаких ограничений, так как все дочерние элементы в RMA_RECEIPTS очищаются. Никаких ограничений не возникает, если я запускаю два оператора по отдельности. Когда блок выполняется, выдается эта ошибка, которая говорит, что rma_detail не может быть удален, потому что записи rma_receipts ссылаются на него. (но их нет ..)

    Error report -
    ORA-02292: integrity constraint (FK_RMA_RECE_REF_23860_RMA_DETA)         violated - child record found
ORA-06512: at line 60
02292. 00000 - "integrity constraint (%s.%s) violated - child record found" *Cause:    attempted to delete a parent key value that had a foreign
           dependency.
*Action:   delete dependencies first then parent or disable constraint.

почему это происходит в блоке? а не по отдельным заявлениям?

1 Ответ

0 голосов
/ 15 января 2019

Общий подход:

delete from child_table where parent_key = ...
delete from parent_table where parent_key = ... 

подвержен ошибкам, если вы включите коммит между двумя шагами. Из-за сроков вы можете столкнуться со следующей проблемой:

Сессия 1:

delete from child_table where parent_key = ...
commit

Сессия 2:

insert a new row into child table for the same parent key

Сессия 1:

delete from parent_table where parent_key = ... 

и вы получите ошибку, потому что (новая) дочерняя запись существует.

Решение простое - уберите коммит. Тогда могут произойти две возможные вещи в зависимости от того, кто попадет первым.

Сессия 1:

delete from child_table where parent_key = ...
delete from parent_table where parent_key = ... 

Сессия 2

tries to insert a new row - and will be blocked waiting for session 1 to either rollback or commit

OR

Сессия 1

delete from parent_table where parent_key = ... 

Сессия 2:

insert a new row into child table for the same parent key

Сессия 1:

delete from parent_table where parent_key = ... 

и сеанс 1 будет заблокирован от удаления родителя до тех пор, пока сеанс 2 не будет откатан или зафиксирован. В любом случае вы всегда будете удалять либо все родительские / дочерние записи, либо все записи, а не поврежденную смесь.

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