Каков наилучший способ вставить дерево из одной таблицы в другую, используя Oracle - PullRequest
2 голосов
/ 24 мая 2011

У меня есть стол, в котором хранятся деревья. Есть node_id и parent_id.

Когда я пытаюсь сделать следующее:

insert into table1 select * from table2 start with node_id = 1 connect by prior node_id = parent_id order by parent_id nulls first

Я получаю эту ошибку:

Error starting at line 6 in command:
insert into table1 select * from table2 start with node_id = 1 connect by prior node_id = parent_id order by parent_id nulls first
Error report:
SQL Error: ORA-02291: integrity constraint (XVTEST.REGIONAL_DEFAULT_DELETE) violated - parent key not found
02291. 00000 - "integrity constraint (%s.%s) violated - parent key not found"
*Cause:    A foreign key value has no matching primary key value.
*Action:   Delete the foreign key or add a matching primary key.

Я понимаю, почему я получаю эту ошибку. Мне просто интересно, есть ли способ сделать это без создания рекурсивной процедуры pl / sql. Мысли? Если это невозможно, у кого-нибудь есть такая процедура, которую я мог бы использовать в качестве образца?

1 Ответ

4 голосов
/ 24 мая 2011

Один из вариантов - создать ограничения FOREIGN KEY как DEFERRABLE, а затем установить их DEFERRED для вашей транзакции, чтобы принудительное применение ограничений внешнего ключа откладывалось до COMMIT.

Обратите внимание, что вы не хотите выполнять SELECT, пока содержимое таблиц нарушает ограничения. В некоторых случаях некоторые операторы SELECT возвращают неожиданные или противоречивые результаты. (Обязательно учитывайте операторы SELECT, выполняемые триггерами.)


-- to create foreign key constraints as deferrable
ALTER TABLE my_table ADD CONSTRAINT my_table_fk1 
FOREIGN KEY (other_table_id) REFERENCES other_table (id)
DEFERRABLE INITIALLY IMMEDIATE;

-- defer all deferrable constraints until the next commit
ALTER SESSION SET CONSTRAINTS=DEFERRED;
-- or
SET CONSTRAINTS ALL DEFERRED;

-- dml operations may now temporarily violate constraints
INSERT ... ; 
UPDATE ... ;

-- you can check the constraints before the commit
SET CONSTRAINTS ALL IMMEDIATE;

-- all deferred constraints will be enforced at the next commit
-- (a fk violation exception will be raised here, rather than by the DML)
COMMIT;

Некоторые полезные ссылки:

http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:914629004506

http://download.oracle.com/docs/cd/B10500_01/server.920/a96524/c22integ.htm#4666


ДОПОЛНЕНИЯ:

Этот подход относится конкретно к базе данных Oracle и может не применяться к другим механизмам реляционных баз данных.

Предупреждение о выполнении SELECTS для таблиц при отложенных ограничениях применяется только к сеансу, который откладывает ограничения. Другие сеансы будут видеть непротиворечивое состояние, так как они не увидят никаких незафиксированных изменений.

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

...