2015-10-04 68 views
0

我正在尝试编写一个PL/SQL过程,用于从供应商表中查找现有主键“supplier_id”并将其替换为新的主键。主键“supplier_id”也是其他几个表的外键。因此我需要更新外键位置。这是我写来解决这个问题的过程:替换主键PL SQL

create or replace PROCEDURE ex5b_supplier_update(supplier_id_delete IN VARCHAR2, 
    supplier_id_update IN VARCHAR2) IS 
    CURSOR supplier_cursor IS 
    SELECT supplier_id 
    FROM supplier; 
    supplier_row supplier_cursor%rowtype; 
    BEGIN 
    OPEN supplier_cursor; 
    LOOP 
    FETCH supplier_cursor INTO supplier_row; 
    EXIT WHEN supplier_cursor%notfound; 

IF ex5b_supplier_exist(supplier_id_delete) THEN 


    UPDATE supplier 
    SET supplier_id = supplier_id_update 
    WHERE supplier_id = supplier_id_delete; 

    UPDATE PURCHASE_ORDER 
    SET supplier_id = supplier_id_update 
    WHERE supplier_id = supplier_id_delete; 

    UPDATE PRODUCT 
    SET supplier_id = supplier_id_update 
    WHERE supplier_id = supplier_id_delete; 

    DBMS_OUTPUT.PUT_LINE('UPDATED'); 
    ELSE 
    DBMS_OUTPUT.PUT_LINE('NOT UPDATED'); 
END IF; 
END LOOP; 
CLOSE supplier_cursor; 
END; 

的过程给了我以下错误:

Error starting at line : 2 in command - BEGIN ex5b_supplier_update('S500','S600');

END;

Error report - ORA-02292: integrity constraint (SYSTEM.PRODUCT_FK) violated - child record found ORA-06512: at "SYSTEM.EX5B_SUPPLIER_UPDATE", line 15 ORA-06512: at line 2 02292. 00000 - "integrity constraint (%s.%s) violated - child record found" *Cause: attempted to delete a parent key value that had a foreign dependency. *Action: delete dependencies first then parent or disable constraint.

总而言之,您无法删除用作外键的主键。但是我也无法更改没有主键的外键。

所以我的问题是我怎么能改变supplier_id和它的所有外键在同一时间,以避免这个错误?

+0

1.插入新的父项。 2.将孩子更新为新父母。 3.删除旧的父母。希望没有人在步骤2和步骤3之间添加新的孩子。或者推迟约束。 –

回答

2

在关系数据库中的主键是保证三两件事:

1) Not nullable 
2) Unique 
3) UNCHANGING 

这是你在这儿违反第三条规则,而你从错误中得到也许你知道为什么。这种方式就是疯狂。 请勿更改主键的值。更改所有你喜欢的属性值,这样行现在看起来完全不同了 - 但不要改变主键。如果您需要认为您需要更改主键,那么您的真正意思是您的主键实际上不是主键。它可能是一个独特的关键,但它根据定义不是主键。

主键不会改变

祝你好运。

编辑

如果你真的想不解除约束和等“变”主键,这里就是你要做的:

  1. 开始交易。
  2. 用新的ID在表格中创建一个新行。
  3. 将“原始”行中除PRIMARY KEY ID COLUMN之外的所有属性复制到“新”行。
  4. 使用引用“原始”行引用“新”行的外键约束更新表中的所有行,即将“旧”ID值更改为“新”ID值。
  5. 删除“原始”行。
  6. 提交交易。

以这种方式完成后,您不违反有关主键的任何规则,并且在事务结束时主键似乎已经更改并且所有FK都已更新。

祝你好运。

+0

有一个办法做到这一点,这是我的任务的要求。当然你不应该这样做,但我没问你是否应该,我问我该怎么做。 – user2725919

+2

只有做到这一点的办法是要么禁用所有的外键依赖故事的约束和与变化继续,并确保您启用外键约束之前,将对应的主键值中的所有家属表,然后启用外键约束。但这并不是所有人都可以接受的主键。 –

+0

@ user2725919:编辑来展示如何做到这一点不违反主键的规则或禁用约束。祝你好运。 –