Как удалить строки с двунаправленными зависимостями? - PullRequest
1 голос
/ 05 октября 2011

Я использую Oracle 10g Express и пытаюсь удалить записи из таблиц с двунаправленными ограничениями.Я пытаюсь распаковать сотни таблиц и зависимостей, сгенерированных с помощью Hibernate (которые нельзя изменить в данный момент), но вот упрощенный пример чрезвычайно :

create table TableA (id number(19,0) not null, ..., rTableA_id number(19,0), primary key (id));
create table TableB (id number(19,0) not null, ..., rTableB_id number(19,0), primary key (id));

alter table TableA add constraint FKA1 foreign key (rTableA_id) references TableB;
alter table TableB add constraint FKB1 foreign key (rTableB_id) references TableA;

Попытка удалить записи из любой таблицы возвращает следующее:
РЕДАКТИРОВАТЬ: это происходит в моем случае с внешними ключами с префиксом SYS_

ORA-02292: integrity constraint (XXX.FKA1) violated - child record found

Я также пытался отключитьограничения, но все попытки бесполезны:

ORA-02297: cannot disable constraint (XXX.FKA1) - dependencies exist

Ответы [ 3 ]

5 голосов
/ 05 октября 2011

Мне интересно, как ваши данные попали в это состояние в первую очередь, так как ваши внешние ключи not null. Если бы обе таблицы были пустыми, вы никогда не сможете вставить строку ни в одну из этих таблиц.

Игнорируя это на мгновение, воссоздавая ваш сценарий, я без проблем отключаю ограничения:

CREATE TABLE tablea(id NUMBER(19, 0) NOT NULL, 
                    rtablea_id NUMBER(19, 0) NOT NULL, 
                    PRIMARY KEY(id))
/

CREATE TABLE tableb(id NUMBER(19, 0) NOT NULL, 
                    rtableb_id NUMBER(19, 0) NOT NULL, 
                    PRIMARY KEY(id))
/

INSERT INTO tablea
VALUES     (1, 2)
/

INSERT INTO tableb
VALUES     (2, 1)
/

ALTER TABLE tablea ADD CONSTRAINT fka1 
                       FOREIGN KEY (rtablea_id)  
                       REFERENCES tableb
/
ALTER TABLE tableb ADD CONSTRAINT fkb1  
                       FOREIGN KEY (rtableb_id)  
                       REFERENCES tablea
/
ALTER TABLE tablea MODIFY CONSTRAINT fka1 DISABLE
/
ALTER TABLE tableb MODIFY CONSTRAINT fkb1 DISABLE
/
delete tablea
/
delete tableb
/
commit
/

Результат:

Table created.
Table created.
1 row created.
1 row created.
Table altered.
Table altered.
Table altered.
Table altered.
1 row deleted.
1 row deleted.
Commit complete.

Я не уверен, как вы получите ошибку ORA-02297 при попытке отключить внешний ключ. Эта ошибка обычно наблюдается при отключении первичного или уникального ключа, на который опирается внешний ключ.

Я подозреваю, что вы действительно хотите установить ограничения initially deferred. Это позволит вам выполнять вставки и удаления для каждой таблицы в отдельности, если соответствующая строка была обновлена ​​или удалена до совершения транзакции:

CREATE TABLE tablea(id NUMBER(19, 0) NOT NULL,  
                    rtablea_id NUMBER(19, 0) NOT NULL,  
                    PRIMARY KEY(id))
/

CREATE TABLE tableb(id NUMBER(19, 0) NOT NULL,  
                    rtableb_id NUMBER(19, 0) NOT NULL,  
                    PRIMARY KEY(id))
/

ALTER TABLE tablea ADD CONSTRAINT fka1 
                       FOREIGN KEY (rtablea_id) 
                       REFERENCES tableb 
                       INITIALLY DEFERRED
/
ALTER TABLE tableb ADD CONSTRAINT fkb1 
                       FOREIGN KEY (rtableb_id) 
                       REFERENCES tablea 
                       INITIALLY DEFERRED
/

INSERT INTO tablea
VALUES     (1, 2)
/

INSERT INTO tableb
VALUES     (2, 1)
/

INSERT INTO tableb
VALUES     (3, 1)
/

COMMIT
/

DELETE tableb
WHERE  id = 2
/

UPDATE tablea
SET    rtablea_id   = 3
WHERE  id = 1
/

COMMIT
/

Результат:

Table created.
Table created.
Table altered.
Table altered.
1 row created.
1 row created.
1 row created.
Commit complete.
1 row deleted.
1 row updated.
Commit complete.
3 голосов
/ 05 октября 2011

Вы уверены, что Hibernate нельзя сказать, чтобы создать ограничения как отложенные? Если DDL не использует ключевое слово DEFERRABLE, ограничения по умолчанию не будут откладываться. Это будет означать, что вы не сможете удалить данные. Если у вас есть схема с циклическими ссылками, вы всегда хотели бы объявить ограничения внешнего ключа отложенными.

Вы можете удалить ограничения, удалить данные, а затем заново создать ограничения (либо используя DDL Hibernate, либо добавив в конце предложение INITIALLY DEFERRED DEFERRABLE). Но это будет серьезной проблемой, если вы удалите данные из любой таблицы с любой частотой. У вас также будут проблемы с вставкой новых данных, если новая строка A хочет сослаться на новую строку B, которую вы создаете.

1 голос
/ 18 декабря 2013

Мне не удалось добавить INITIALLY DEFERRED, поскольку базы данных (а также базовые сценарии Hibernate) уже существуют. Для новых систем это было бы вариантом, однако, есть много инструментов (из которых я знаю только несколько), которые полагаются на базу данных в ее текущей форме, и я слишком боялся каких-либо непреднамеренных побочных эффектов, добавляя этот параметр в 700 столов.

Поэтому я использовал следующее решение:

alter table TableA MODIFY CONSTRAINT FKA1 DISABLE;
alter table TableB MODIFY CONSTRAINT FKB1 DISABLE;

delete from TableA where id = 1;
delete from TableB where id = 2;

alter table TableA MODIFY CONSTRAINT FKA1 ENABLE;
alter table TableB MODIFY CONSTRAINT FKB1 ENABLE;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...