【问题标题】:Update Table with foreign key in oracle 10.2在 oracle 10.2 中使用外键更新表
【发布时间】:2012-08-02 08:22:14
【问题描述】:

我有一张表ROUTE_DETAILS,列ROUTE_NUMBERROUTE_NAME

我有另一张表 CUSTOMER_DETAILS 与列 CUST_CODECUST_NAMEROUTE_NUMBER。这里的路由号是ROUTE_DETAILS的外键。

ROUTE_DETAILS 是父表,CUSTOMER_DETAILS 是子表。

ROUTE_DETAILS中的数据:

ROUTE_NUMBER ROUTE_NAME RN0001 路线1 RN0002 路线2 注册护士路线3

CUSTOMER_DETAILS中的数据:

CUST_CODE CUST_NAME ROUTE_NUMBER CC0001 客户1 RN0001 CC0002 客户 2 注册护士

现在的问题是当我尝试从 ROUTE_DETAILS 更新 ROUTE_NUMBER 或从 CUSTOMER_DETAILS 更新 ROUTE_NUMBER 时显示错误:发现完整性约束违反子记录

查询是:

update ROUTE_DETAILS 
   set ROUTE_NUMBER = 'RN0003' 
 where ROUTE_NUMBER = 'RN'

当我尝试更新 customer_details 时也会发生同样的事情。

【问题讨论】:

    标签: oracle oracle10g


    【解决方案1】:

    我看到的唯一选择是将 FK 约束更改为“DEFERRABLE”。

    然后您可以在单个事务中更改两行,因为在您提交数据时会检查约束:

    update ROUTE_DETAILS set ROUTE_NUMBER ='RN0003' where ROUTE_NUMBER ='RN';
    update CUSTOMER_DETAILS set ROUTE_NUMBER ='RN0003' where ROUTE_NUMBER ='RN';
    commit;
    

    有关如何更改 FK 约束的详细信息,请参阅手册。

    如果您将约束设置为“INITIALLY IMMEDIATE”,则需要在运行更新之前运行set constraints deferred

    编辑,这里是一个完整的例子:

    设置表和约束:

    create table route_details
    (
     route_number varchar(20) not null primary key
    );
    
    create table customer_details
    (
       cust_code varchar(20) not null primary key,
       route_number varchar(20) not null
    );
    
    alter table customer_details
      add constraint fk_route_number 
         foreign key (route_number)
         references route_details (route_number)
      deferrable
      initially immediate;
    
    
    insert into route_details (route_number)
    values ('RN0001');
    
    insert into route_details (route_number)
    values ('RN');
    
    insert into customer_details (cust_code, route_number)
    values ('CC0001', 'RN0001');
    
    insert into customer_details (cust_code, route_number)
    values ('CC0002', 'RN');
    
    commit;
    

    运行更新:

    set constraints all deferred;
    
    update ROUTE_DETAILS set ROUTE_NUMBER ='RN0003' where ROUTE_NUMBER ='RN';
    update CUSTOMER_DETAILS set ROUTE_NUMBER ='RN0003' where ROUTE_NUMBER ='RN';
    commit;
    

    【讨论】:

    • @ManishSasmal:"not working" 不是有效的 Oracle 错误消息。您确实更改了外键的定义,是吗?
    • 我不是那个意思。我说的是这个程序失败了.. 遵循乔的回答,它会更好,更有效..
    • @ManishSasmal:查看我的编辑(顺便说一句:“失败”也不是有效的错误消息)
    【解决方案2】:

    是的,如果孩子正在引用该键值,则您无法更新父主键。

    您也不能将子表更新为具有不引用父表中主键值的外键值。

    所以,你可以:

    1)在您进行更改时暂时放松约束,确保之后重新应用它。

    或者

    2)删除子行,更新父行,然后用新的外键值重新插入子行。

    【讨论】:

      【解决方案3】:

      对此有两个想法...

      首先,您不应该更改主键的值,主键的全部意义在于它不会改变。

      如果您必须进行此更改,我知道有两种方法可以做到。

      1. 在 route_details 中插入“RN0003”作为新行。然后更新所有受影响的客户。然后删除 RN 行。所以:

        插入 route_number 值 ('RN0003','ROUTE3');

        更新 customer_details set route_number = 'RN0003' where route_number = 'RN';

        从 route_details 中删除 route_number = 'RN';

      2. 使用此处描述的延迟键:

      http://www.orafaq.com/wiki/Foreign_key

      【讨论】:

      • 我相信“主键”的定义表明它是唯一的,而不是它不会改变。理想情况下它不需要改变,但它确实会发生在现实生活中,事情是混乱的。
      【解决方案4】:

      参考动作包括ON UPDATE

      *CASCADE:删除或更新父表中的行,并自动删除或更新子表中匹配的行。支持ON DELETE CASCADEON UPDATE CASCADE

      因此您可以对your foreing key 使用ON UPDATE CASCADE 参考操作。

      alter table customer_details
        add constraint fk_route_number 
           foreign key (route_number)
           references route_details (route_number)
           ON UPDATE CASCADE;
      

      对于 NDB 表,不支持 ON UPDATE CASCADE

      【讨论】:

        猜你喜欢
        • 2010-11-26
        • 1970-01-01
        • 1970-01-01
        • 2010-12-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-04
        • 1970-01-01
        相关资源
        最近更新 更多