开发者

What is the best way to insert a tree from one table to another using Oracle

开发者 https://www.devze.com 2023-03-08 13:57 出处:网络
I have a table that stores trees. There is a node_id and parent_id. When I try the following: insert into table1 select * from table2 start开发者_运维百科 with node_id = 1 connect by prior node_id

I have a table that stores trees. There is a node_id and parent_id.

When I try the following:

insert into table1 select * from table2 start开发者_运维百科 with node_id = 1 connect by prior node_id = parent_id order by parent_id nulls first

I get this error:

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.

I understand why I am getting this error. I was just wondering if there was a way to do this with out making a recursive pl/sql procedure. Thoughts? If it is not possible does anyone have a procedure that like this that I could use as a sample?


One option is to create the FOREIGN KEY constraints as DEFERRABLE, and then set them DEFERRED for your transaction, so the enforcement of the foreign key constraints is deferred until the COMMIT.

Note that you don't want to perform any SELECT while the contents of the tables violate the constraints. In some cases, some SELECT statements will return unexpected or inconsistent results. (Be sure to consider SELECT statements performed by triggers.)


-- 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;

Some helpful references:

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


ADDENDA:

This approach applies specifically to Oracle database, and may not be applicable to other relational database engines.

The warning against performing SELECTS against the tables while the constraints are deferred applies only to the session that defers constraints. Other session will see a consistent state, since they will not see any uncommitted changes.

Using DEFERRED constraints is preferred over disabling and re-enabling the constraints, since disabling constraints would affect all sessions, and re-validating the constraints can consume significant resources (for large tables).

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号