如何更新FK指向的记录PK

时间:2017-05-14 10:14:39

标签: oracle transactions

我在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

我知道我做了一些错误的事情,但我不知道该怎么做以及如何谷歌。

感谢。

3 个答案:

答案 0 :(得分:0)

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

  1. 在stu_choose_lesson,leave_apply,message表中禁用FK约束(指向student表中的studentNum列)。
  2. 更新stu_choose_lesson,leave_apply,消息表中的记录。
  3. 更新学生表中的记录。 (请注意,sturent表必须是最后一个要更新的表,因为它是带主键的通道)
  4. 在stu_choose_lesson,leave_apply,message表中启用FK约束(第一步中禁用的约束)。
  5. 以下脚本应该适合您,只需将约束名称替换为stu_choose_lesson,leave_apply,message表中的约束名称:

    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;
    /
    

答案 1 :(得分:0)

所以这是描述你的问题的最小例子

<强>设置

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),并且约束的重新验证将是 deferrend ,直到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学生记录。即使用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;

答案 2 :(得分:0)

如果你的课程&#34;是改变主键的价值,你的教训是教你做错事。您永远不应该更改主键的值 - 而应该插入新记录并删除旧记录。主键有三个属性:

  1. 永远不会是NULL。
  2. 这是独一无二的。
  3. 永远不会改变。
  4. 您遇到困难的原因是您违反了规则#3。

    不要这样做!