如果你有一对带有数字主键和父子关系的表,那么在这些表中复制记录的最佳方法是什么,因为如果你把它作为两个单独的插入来实现,那么父键的关键是已经改变了?
或许最好用一个例子来解释。假设您有以下表格结构:
CREATE TABLE APARENT (
APARENT_CODE NUMBER, -- primary key
AVALUE1 NUMBER,
AVALUE2 NUMBER
);
CREATE TABLE ACHILD (
ACHILD_CODE NUMBER, -- primary key
APARENT_CODE NUMBER, -- foreign key
AVALUE3 NUMBER
);
APARENT
中的值是父记录。他们可能在ACHILD
表格中有许多记录,并通过APARENT_CODE
字段链接回来。
复制记录的最佳方式是什么(包括单个父记录和多个子记录)?我的困惑是因为当您将重复记录插入父表时,您必须更改主键值(在这种情况下通过序列),因此当您插入子记录时,您如何知道链接它们的外键值到?
编辑抱歉,编辑以防不清楚:第一次插入是复制多条记录,因此CURRVAL不能用于第二次插入。
目前我正在使用此代码:
CREATE TABLE TMP_CODES (
OLD_APARENT_CODE NUMBER,
NEW_APARENT_CODE NUMBER
);
INSERT INTO TMP_CODES
SELECT APARENT_CODE,
SQ_APARENT.NEXTVAL -- gets new sequence value
FROM APARENT
WHERE AVALUE1 = 10;
INSERT INTO APARENT
SELECT C.NEW_APARENT_CODE, -- the copied parent records get a new sequence value
A.VALUE1,
A.VALUE2
FROM APARENT A,
TMP_CODES C
WHERE A.AVALUE1 = 10
AND C.OLD_APARENT_CODE = A.APARENT_CODE;
INSERT INTO ACHILD
SELECT SQ_ACHILD.NEXTVAL, -- a new sequence value for the primary key
C.NEW_APARENT_CODE, -- this inserts the correct link value
A.VALUE3
FROM ACHILD A,
TMP_CODES C
WHERE C.OLD_APARENT_CODE = A.APARENT_CODE;
我只是想知道是否有更有效的方法,而不是先将所有代码都表达到临时表中。
我正在使用Oracle 10.感谢您的帮助。
答案 0 :(得分:1)
如果您使用NEXTVAL和CURRVAL作为父表的序列,则不需要临时表。
INSERT INTO APARENT
SELECT SQ_APARENT.NEXTVAL,
A.VALUE1,
A.VALUE2
FROM APARENT
WHERE A.AVALUE1 = 10
INSERT INTO ACHILD
SELECT SQ_ACHILD.NEXTVAL, -- a new sequence value for the primary key
SQ_APARENT.CURRVAL, -- this inserts the correct link value
A.VALUE3
FROM ACHILD A
WHERE A.APARENT_CODE = 10;
答案 1 :(得分:1)
在单个语句中插入行并获取生成的序列值的常用方法是使用RETURNING INTO
clause。不幸的是,这个条款是not supported with the multi-row INSERT SELECT
statement(截至11.2.0.2.0)。
所以你必须要么:
使用游标并逐行插入父表(然后在子表中为父表中的每一行使用一个多行插入)。
例如,在您的情况下:
DECLARE
l_key aparent.aparent_code%TYPE;
BEGIN
FOR cc IN (SELECT a.aparent_code, a.value1, a.value2
FROM aparent a
WHERE a.avalue1 = 10) LOOP
INSERT INTO aparent
VALUES (sq_aparent.nextval, cc.value1, cc.value2)
RETURNING aparent_code INTO l_key; -- get the new parent key
INSERT INTO achild
(SELECT sq_achild.nextval, l_key, value3 -- use the new parent key
FROM achild
WHERE aparent_code = cc.aparent_code);
END LOOP;
END;
我认为您的方法通常可能是最有效的,特别是如果要复制许多父行。与许多单行语句产生的大量开销相比,插入临时表并加入它的开销应该是最小的。