【问题标题】:How to update a record's PK which with FK point to如何更新带有 FK 指向的记录的 PK
【发布时间】:2017-05-14 10:14:39
【问题描述】:

我在 Oracle 中有一个这样的数据库

stu_choose_lesson ----> student <-----leave_apply
                          /|\
                           |
                           |
                           |-------message

然后,我有一个作业可以让我更新学生中的记录,并且根据要求我不能使用“更新时”。

我在 sqlplus 中运行这些命令。

BEGIN
UPDATE student SET studentNum=200204 WHERE studentNum=200202;
UPDATE stu_choose_lesson SET studentNum=200204 WHERE studentNum=200202;
UPDATE leave_apply SET studentNum=200204 WHERE studentNum=200202;
UPDATE message SET studentNum=200204 WHERE studentNum=200202;
END;
/

然后我得到这个错误。

ORA-02292: integrity constraint (SYSTEM.SYS_C007646) violated - child record found
ORA-06512: at line 1

我在谷歌上搜索并执行此操作。

SET CONSTRAINTS SYS_C007647 DEFERRED;

但我收到此错误。

ORA-02447: cannot defer a constraint that is not deferrable

我知道我做错了一些事情,但我不知道该怎么做,也不知道怎么用谷歌搜索。

谢谢。

【问题讨论】:

  • 您可以使用 CTE 并在单个语句中更新它
  • @AluanHaddad 作业要求是“使用事务进行后续更新:将studentNum从'200202'更新为'200204',同时更新所有FK(不要在更新时使用)。 "所以,我不知道CTE是否达到要求。

标签: oracle transactions


【解决方案1】:

当与另一个表中的另一个记录存在 PK-FK 关系时,Oracle 不会让您更新记录。您可以按照以下步骤操作:

  1. 在 stu_choose_lesson、leave_apply 和消息表中禁用 FK 约束(指向学生表中的 studentNum 列)。
  2. 更新 stu_choose_lesson、leave_apply、消息表中的记录。
  3. 更新学生表中的记录。 (注意,sturent 表必须是最后一个要更新的,因为它是带有主键的 kone)
  4. 在 stu_choose_lesson、leave_apply 和消息表中启用 FK 约束(在第一步中禁用的约束)。

以下脚本应该适合您,只需将约束名称替换为您的 stu_choose_lesson、leave_apply 和消息表中的名称:

BEGIN
alter table stu_choose_lesson
DISABLE constraint
<your FK_constraint name goes here>;

alter table leave_apply
DISABLE constraint
<your FK_constraint name goes here>;

alter table message
DISABLE constraint
<your FK_constraint name goes here>;

UPDATE stu_choose_lesson SET studentNum=200204 WHERE studentNum=200202;
UPDATE leave_apply SET studentNum=200204 WHERE studentNum=200202;
UPDATE message SET studentNum=200204 WHERE studentNum=200202;
UPDATE student SET studentNum=200204 WHERE studentNum=200202;

alter table stu_choose_lesson
ENABLE constraint
<your FK_constraint name goes here>;

alter table leave_apply
ENABLE constraint
<your FK_constraint name goes here>;

alter table message
ENABLE constraint
<your FK_constraint name goes here>;
END;
/

【讨论】:

    【解决方案2】:

    所以这是一个描述您的问题的最小示例

    设置

    create table student (id number, name varchar2(100));
    alter table student add  primary key (id);
    
    create table student_lesson (id number, student_id number);
    alter table student_lesson add  primary key (id);
    alter table student_lesson add constraint
       fk_student_lesson FOREIGN KEY (student_id)
       references student (id);
    
    -- data
    insert into student (id,name) values(1,'x');
    insert into student_lesson (id,student_id) values(1,1);
    commit;
    

    问题

    update student set id = 2 where id = 1;
    -- fails with ORA-02292
    

    问题是,不是deferrable 中的约束在第一次更新时会使 FK 约束无效。

    解决方案 1 删除约束并定义它DEFERRABLE

    alter table student_lesson drop constraint fk_student_lesson;
    alter table student_lesson add constraint
       fk_student_lesson FOREIGN KEY (student_id)
       references student (id) 
       initially deferred deferrable;
    

    现在您可以更新两条记录(PK 和 FK),并且约束的重新验证将推迟直到COMMIT

    update student set id = 2 where id = 1; 
    update student_lesson set student_id = 2 where student_id = 1; 
    commit
    

    解决方案2 如果不能修改约束,不要执行更新,而是INSERT新的STUDENT记录,更新子表和DELETE旧的student记录。 IE。使用 INSERT + DELETE 执行UPDATE 逻辑

    insert into student (id,name) values(2,'x');
    update student_lesson set student_id = 2 where student_id = 1; 
    delete from student where id = 1;
    commit;
    

    【讨论】:

      【解决方案3】:

      如果您的“课程”是更改主键的值,那么您的课程就是在教您做错事。您永远不应该更改主键的值 - 相反,应该插入新记录并删除旧记录。主键具有三个属性:

      1. 它永远不会为 NULL。
      2. 它是独一无二的。
      3. 它永远不会改变。

      您遇到困难的原因是您违反了第 3 条规则。

      不要这样做!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-06-21
        • 2015-07-03
        相关资源
        最近更新 更多