博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
约束5:外键约束
阅读量:5745 次
发布时间:2019-06-18

本文共 2781 字,大约阅读时间需要 9 分钟。

在关系型数据库中,表与表之间存在引用关系,也就是说,数据列C1引用其他表的数据列C2中存在的值,引用关系通过外键(Foreign Key )约束实现。如果表(TableA)中的列C1被其他表引用,那么,我们把表(TableA)称作参考表,或引用表(Referenced Table),该列C1是其他表的参考列,或引用列(Referenced Column),对引用列执行Update 或 Delete 操作会受到很多限制。某些情况下,也把参考表称作父表,把引用父表的列称作子列,或外键列。

[ FOREIGN KEY ]           REFERENCES [ schema_name . ] referenced_table_name [ ( ref_column ) ]           [ ON DELETE { NO ACTION | CASCADE | SET NULL | SET DEFAULT } ]           [ ON UPDATE { NO ACTION | CASCADE | SET NULL | SET DEFAULT } ]

例如,在数据列C1和C2之间创建外键约束,C1是引用列,C2列引用C1列的值,外键约束的特点:

  • 如果C2列的值不是NULL,那么C2列的值必须存在于C1列中,否则,系统返回违反外键约束的错误;
  • 外键约束可以创建在同一个表的不同列之间,这种引用类型称作自引用;
  • 外键约束可以引用单列,也可以引用多列;
  • 外键约束只能引用那些构成主键或唯一约束的数据列,或者唯一索引键列,也就是说,外键约束的引用列(单列或复合列)必须是唯一的;

一,外键约束的级联操作

当引用列的值被更新(UPDATE或DELETE)时,子列会采取相应的动作:

  • 默认行为是NO ACTION:如果子列引用父表的值,那么父表的更新操作被回滚,数据库抛出错误;
  • 级联操作(CASCADE):当父表删除数据行A时,子表删除引用该数据行A的所有行;当父表更新数据行B时,子表把引用该数据行B的所有数据行都更新为新值;
  • 置空(SET NULL):当父表更新数据行A时,子表把引用该数据行A的所有数据行都设置为NULL,该设置要求外键列必须可空(nullable);
  • 设置默认值(SET DEFAULT):当父表更新数据时,子表把引用该数据行的数据行都设置为外键列的默认值,该设置要求外键列必须有默认值定义,如果构成外键的某一个列,没有显式定义默认值,并且可为NULL,那么系统把NULL作为列的默认值。

这些级联操作是系统预定义的,不能更改。

二,手动更新外键

在对引用列进行更新操作(Update 和 Delete)之前,必须禁用外键约束,然后手动更新,最后再次启用外键约束。手动更新外键,给用户提供了很大的灵活性,由用户保证外键约束的有效性。

1,查看外键列的信息

使用 sys.foreign_keyssys.foreign_key_columns 这两个系统表获取外键约束的信息

select fk.object_id as FK_Object_ID,    fk.name as FK_name,    pt.name as ParentTable_Name,    pc.name as ParentTable_Column_Name,    rt.name as ReferencedTable_Name,    rc.name as ReferencedTable_Column_Namefrom sys.foreign_keys fk with(nolock)inner join sys.foreign_key_columns fkc with(nolock)    on fk.object_id=fkc.constraint_object_idinner join sys.tables pt with(nolock)    on fkc.parent_object_id=pt.object_idinner join sys.columns pc with(nolock)    on fkc.parent_object_id=pc.object_id         and fkc.parent_column_id=pc.column_idinner join sys.tables as rt with(nolock)    on fkc.referenced_object_id=rt.object_idinner join sys.columns rc with(nolock)    on fkc.referenced_object_id=rc.object_id         and fkc.referenced_column_id=rc.column_idwhere rt.name=N'Referenced_Table_name
View Code

2,禁用外键列

--disable FK constraintalter table ParentTable_namenocheck constraint FK_name

将外键 nocheck之后,可以使用 Delete 或 Update 命令更新数据,但是,当使用 Truncate 命令时,依然会报错

Cannot truncate table 'xxx' because it is being referenced by a FOREIGN KEY constraint.

3,启用外键列

--enable FK constraintalter table ParentTable_namecheck constraint FK_name

三,扩展引用完整性

系统自定义的外键约束,由很多限制,例如,引用列和外键列必须在相同的服务器上,相同的数据库中,不支持跨数据库的外键约束。而外键约束,实际上,就是一列引用另外一列的值,这个功能可以由触发器来实现,用于扩展引用完整性。触发器的实现过程是:创建INSTEAD OF触发器,在插入数据之前,检查插入的数据是否存在于参考表中,如果存在,插入成功;如果不存在,回滚事务,抛出异常。

CREATE TRIGGER schema_name.trigger_name   ON table_nameINSTEAD OF { [ INSERT ] [ , ] [ UPDATE ] }   AS { sql_statement  [ ; ] [ ,...n ] }

在DML触发器中,有两个特殊的系统表inserted和deleted,用于表示插入的新数据和删除的旧数据。

 

参考文档:

转载地址:http://dqxzx.baihongyu.com/

你可能感兴趣的文章
桌面支持--打不开网页上的pdf附件解决办法(ie-tools-compatibility)
查看>>
nagios监控windows 改了NSclient++默认端口 注意事项
查看>>
干货 | JAVA代码引起的NATIVE野指针问题(上)
查看>>
POI getDataFormat() 格式对照
查看>>
Python 中的进程、线程、协程、同步、异步、回调
查看>>
好的产品原型具有哪些特点?
查看>>
实现java导出文件弹出下载框让用户选择路径
查看>>
刨根问底--技术--jsoup登陆网站
查看>>
OSChina 五一劳动节乱弹 ——女孩子晚上不要出门,发生了这样的事情
查看>>
Spring--通过注解来配置bean
查看>>
pandas 十分钟入门
查看>>
nginx rewrite
查看>>
前端安全系列(一):如何防止XSS攻击?
查看>>
查看Linux并发连接数
查看>>
你是谁不重要,关键是你跟谁!
查看>>
CSS中规则@media的用法
查看>>
pychecker:分析你的python代码
查看>>
我的友情链接
查看>>
DNS显性+隐性URL转发原理
查看>>
我的友情链接
查看>>