Cascade INSERT使用SEQUENCE - ORACLE

时间:2014-08-04 04:50:08

标签: sql oracle plsql

我需要从两个表中复制记录并再次将它们重新插入到这些表中,只有一个字段不同(父表为PK,子表为PK,FK)。 PK可以从SEQUENCE中获取,我面临的问题是如何级联更新子表中的FK。

我有下表 My_List ,其中 Sup_ID 是主键

My_List

+--------+----------+-----------+
| Sup_ID | Sup_Name |  Sup_Code |
+--------+----------+-----------+
|      1 | AA       |        23 |
|      2 | BB       |        87 |
|      3 | CC       |        90 |
+--------+----------+-----------+

下表 My_List_details ,其中 Buy_ID 是主键(取自SEQUENCE,假定已创建), Sup_ID 是外键点在 My_List.Sup_ID

My_List_details

+--------+--------+------------+------------+------------+
| Buy_ID | Sup_ID | Sup_Detail | Max_Amount | Min_Amount |
+--------+--------+------------+------------+------------+
|     33 |      1 | AAA        |          1 |         10 |
|     34 |      2 | BBB        |         11 |         20 |
|     35 |      3 | CCC        |         21 |         30 |
|     36 |      2 | BBB        |         11 |         20 |
+--------+--------+------------+------------+------------+

-------------------------------------------- -------

目标

写PL / SQL函数执行以下操作:

  1. 复制 My_List 记录,然后重新插入新PK - > Sup_ID 取自SEQUENCE的值。
  2. 复制 My_List_details 记录,并根据My_List.Sup_ID和SEQUENCE的Buy_ID重新插入新的 Sup_ID 外键。
  3. -------------------------------------------- ----------------------------------

    预期结果

    My_List

    +--------+----------+----------+
    | Sup_ID | Sup_Name | Sup_Code |
    +--------+----------+----------+
    |      1 | AA       |       23 |
    |      2 | BB       |       87 |
    |      3 | CC       |       90 |
    |      4 | AA       |       23 |
    |      5 | BB       |       87 |
    |      6 | CC       |       90 |
    +--------+----------+----------+

    My_List_details

    +--------+--------+------------+------------+------------+
    | Buy_ID | Sup_ID | Sub_Detail | Max_Amount | Min_Amount |
    +--------+--------+------------+------------+------------+
    |     33 |      1 | AAA        |          1 |         10 |
    |     34 |      2 | BBB        |         11 |         20 |
    |     35 |      3 | CCC        |         21 |         30 |
    |     36 |      2 | BBB        |         11 |         20 |
    |     37 |      1 | AAA        |          1 |         10 |
    |     38 |      2 | BBB        |         11 |         20 |
    |     39 |      3 | CCC        |         21 |         30 |
    |     40 |      2 | BBB        |         11 |         20 |
    +--------+--------+------------+------------+------------+

    我开始的是以下内容:

    BEGIN
        FOR   d  IN (
                        SELECT  Sup_Name, Sup_Code
                        FROM    My_List
                    )
        LOOP
            INSERT INTO MY_List SELECT Sup_ID.NEXTVAL, Sup_Name, Sup_Code 
        END LOOP;
    END;
    /
    

    但是,我不确定以下内容:

    • 如何使用My_List中的PK新值替换My_List_Details中的FK。 My_List_Detail
    • 扩展函数以更新任意数量的子表(级联更新),(例如,五个表的FK指向My_List的PK,需要以相同的方式更新)。

2 个答案:

答案 0 :(得分:0)

我认为好的解决方案是通过附加列扩展所有主键,当克隆记录发生时,该列将通过触发器递增。 我们称这个附加列为SEC_ID。 SEC_ID应该在一个主键的上下文中递增和使用。 您不必在表中创建与SEC_ID列一样多的序列。您可以在触发器中查询最后一个sec_id作为您的ID,然后将其递增以插入具有原始ID的新有效主键。

优点:

简单机制

简单扩展新表

答案 1 :(得分:0)

我发现以下内容解决了我的问题(假设sup_seq和buy_seq是两个创建的SEQUENCES):

DECLARE
   CURSOR cOld IS
      SELECT *
      FROM my_list;

   new_id  NUMBER;
BEGIN
   FOR rOld IN cOld LOOP
      new_id := sup_seq.NEXTVAL;  -- Get the ID to use for the new row

      INSERT INTO my_list
             (sup_id,sup_name,sup_code)
      VALUES (new_id,rOld.sup_name,rOld.sup_code);

      INSERT INTO my_list_details
            (buy_id,sup_id,sup_detail,max_amount,min_amount)
      SELECT buy_seq.NEXTVAL,new_id,sup_detail,max_amount,min_amount
      FROM   my_list_details
      WHERE  sup_id = rOld.sup_id;
   END LOOP;
END;

如果问题可以通过其他方式解决,可能不建议使用光标,对我来说,我发现它更容易阅读和维护。