指定外键是否会自动更新外表的值?

时间:2017-10-17 20:07:46

标签: sql oracle foreign-keys

我有两张表:studentfaculty

我在student表中添加了一列,该列是引用faculty中列的外键。

让我们说教师的身份 更改 。根据下面的代码,我的student表会相应更新吗?或者我是否需要做额外的事情以确保更新?例如,假装James的id从1更新为99. student的advisorid列会相应更新吗?

注意 - 我正在使用LINQPad而我无法对此进行测试,因为当我尝试对引用的表进行更改时,我得到Error 547: The UPDATE statement conflicted with the REFERENCE constraint "FK__enroll__studenti__178D7CA5". The conflict occurred in database "tempdb", table "dbo.enroll", column 'studentid'

alter table student
add advisorid int foreign key(advisorid) references faculty(facultyid);

update student set advisorid = 1 where studentid = 1;

select * from student

select * from faculty;

enter image description here

2 个答案:

答案 0 :(得分:1)

正如您所见,默认情况下,外键所基于的键的更新不会传播到依赖列。您可以通过指定on update子句来获得此类行为:

alter table student
add advisorid int foreign key(advisorid) references faculty(facultyid)
on update cascade;

修改
要回答注释中的问题,还可以在删除行时定义行为:

alter table student
add advisorid int foreign key(advisorid) references faculty(facultyid)
on delete cascade
on update cascade;

答案 1 :(得分:0)

在Oracle中ON UPDATE CASCADE不起作用。在这里,我将演示另一种更新方案。 不是指定ON UPDATE CASCADE,而是可以将约束的检查推迟到事务结束。因此约束必须是DEFERRABLE。遗憾的是,无法修改约束,因此必须删除并重新创建约束。

这是一个例子:

CREATE TABLE parent_ (
   pid NUMBER CONSTRAINT pk_parent PRIMARY KEY,
   c1  VARCHAR2(50)
);

CREATE TABLE child_ (
   cid NUMBER,
   pid NUMBER CONSTRAINT fk_child_parent REFERENCES parent_(pid) ON DELETE CASCADE, --DEFERRABLE,
   c1  VARCHAR2(50)
);

INSERT INTO parent_ VALUES (1, 'two');
INSERT INTO child_ VALUES (2, 1, 'two');

COMMIT;

更新主键或外键将导致oracle异常

UPDATE parent_ SET pid = 2
Fehlerbericht -
SQL-Fehler: ORA-02292: integrity constraint (ME.FK_CHILD_PARENT) violated - child record found
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.

UPDATE child_ SET pid = 2
Fehlerbericht -
SQL-Fehler: ORA-02291: integrity constraint (ME.FK_CHILD_PARENT) violated - parent key not found
02291. 00000 - "integrity constraint (%s.%s) violated - parent key not found"
*Cause:    A foreign key value has no matching primary key value.
*Action:   Delete the foreign key or add a matching primary key.

现在外键将被重新创建为可延迟。它仍然会导致外键约束违规,但可以设置为每个会话延迟。优点是所有其他会话仍然像以前一样。

ALTER TABLE child_ DROP CONSTRAINT fk_child_parent;
ALTER TABLE child_ ADD CONSTRAINT fk_child_parent FOREIGN KEY (pid) REFERENCES parent_(pid) ON DELETE CASCADE DEFERRABLE;

ALTER SESSION SET CONSTRAINTS = DEFERRED;

UPDATE parent_ SET pid = 2;
UPDATE child_ SET pid = 2;

COMMIT;

ALTER SESSION SET CONSTRAINTS = IMMEDIATE;

创建外键(也是内联)时也可以设置DEFERRABLE属性。在official documentation

中详细了解相关信息