外键约束详解

外键约束详解

先要理清几个概念:

1候选键(CandidateKey关系中的一个属性组,其值能唯一标识一个元组,若从该属性组中去掉任何一个属性,它就不具有这一性质了,这样的属性组称作候选键(候选码)。

2主键(PrimaryKey:当有多个候选键时,可以选定一个作为主键,选定的候选键称为主键(主码)。

主键唯一标识表中的每行记录。主键约束有如下特点:每个表中只能有一个主键,主键可以是一列,也可以是多列的组合;主键值必须唯一并且不能为空,对于多列组合的主键,某列值可以重复,但列的组合值必须唯一。

3外键(Foreign Key关系R中的一个属性组,它不是R的候选键,但它与另一个关系S的候选键相对应,则称这个属性组为R的外键(外码)。关系R称为参照关系(参照表、从表),关系S称为被参照关系(被参照表、主表)

外键是指一个表(从表)中的一列或列组合,它虽不是该表的主键,但却是另一个表(主表)的主键。通过外键约束可以为相关联的两个表建立联系,实现数据的引用完整性,维护两表之间数据的一致性关系。

特殊情况下,参照关系和被参照关系可以是同一个关系。即,特殊情况下,从表和主表可以是同一个表。

参照[引用]关系(Referencing Relation)、子表、从表、外键表、参照[引用]表,这些作为同一术语的同义词使用。

被参照[被引用]关系(Referenced Relation)、父表、主表、主键表、被参照[被引用]表、查找表,这些作为同一术语的同义词使用。

请注意,在英语国家讲数据库的英语文献中,relation有时指“表”,有时指两表之间的联系(relationship)。指两表之间的relationship时也常用link[链接]

relationshiprelation通常都翻译为关系,但在数据库中两者含义不同。relationship[关系;联系;关联],在数据库中指不同表之间的数据彼此联系的方法。数据库表之间的表之间的relationship有:一对一、一对多、多对多。relation[关系],在数据库指表,从本质上说,关系是一个包含行和列的二维表或数组。应根据语境区别理解。

 

例、有两个关系:

student (s#, sname, d#),即学生这个关系有三个属性:学号,姓名,所在系别

department(d#, dname),即院系有两个属性:系号、系名

s#、d#是各自所在关系的主键,d#还是关系student的外键。student是参照关系(从表),department是被参照关系(主表)。

 

建立外键约束(FOREIGN KEY)后,从表中的外键的取值,要么在主表有对应的值,要么为NULL,但不能是主表中没有对应的值。特殊情况下,从表和主表可以是同一个表。

通过外键能实现数据的参照完整性(Referential Integrity引用完整性),参照完整性约束意味着,从表中某列(外键列)和主表中的某列(主键或UNIQUE约束)匹配。这些列称为对应列(有时也称为公共字段)。

外键既能确保数据完整性,也能表现表之间的关系(relationship)。也就是说,如果你为引用表(从表)定义了外键,就在你定义外键的表(从表、引用表)和外键引用的表(主表、被引用表)之间既确保了数据完整性也确定了两表之间的关系。

◇建立外键约束后,从表中的外键的取值,要么在主表有对应的值,要么为NULL,通过定义引用列(从表中的外键)为NOT NULL,可以确保外键的取值必须在主表有对应的值。

☆建立参照完整性约束后的级联动作受{ON DELETE | ON UPDATE} { NOACTION | CASCADE | SET NULL | SET DEFAULT }决定,默认拒绝(NO ACTION)。

 

建立外键约束后,DBMS将执行参照完整性检查和违约处理:

被参照表(主表,例如department

参照表(从表,例如student

违约处理(破坏参照完整性时的处理)

可能破坏参照完整性

插入元组操作》

拒绝执行

可能破坏参照完整性

更新外键值操作》

拒绝执行

删除元组操作》

可能破坏参照完整性

拒绝执行/级联删除/设置为空值/设置为默认②

更新主键值操作①》

可能破坏参照完整性

拒绝执行/级联更新/设置为空值/设置为默认

[]拒绝执行时,将产生一个错误提示。

①更新主表中的主键(或UNIQUE约束列的)值操作。

②由ON DELETE { NO ACTION | CASCADE | SET NULL | SETDEFAULT }决定,默认拒绝执行(NO ACTION)。

③由ON UPDATE { NO ACTION | CASCADE | SET NULL | SETDEFAULT }决定,默认拒绝执行(NO ACTION)。


建立外键约束后,DBMS将如下检查处理:

外键约束对子表如此检查处理:

在子表上进行INSERTUPDATE操作的限制是,要和主表中的主键值匹配,或为NULL,否则不允许。

外键约束对父表如此检查处理:

在父表上进行UPDATEDELETE操作的限制,取决于在定义子表的外键时指定的ON UPDATEON DELETE子句(不同的DBMS支持的情况不尽相同)。

ON DELETE子句各选项的作用:

NO ACTION:删除主表记录,如果子表中有和主表匹配的记录,则不允许(产生一个错误提示)。此为默认操作(不指定ON DELETE子句,系统自动采取的操作)。

CASCADE(级联):删除主表记录,也将删除子表中的匹配记录。

SET NULL:删除主表记录,将子表中的匹配记录的外键值改为NULL

SET DEFAULT:删除主表记录,将子表中的匹配记录的外键值改为默认值。

ON UPDATE子句各选项的作用:

NO ACTION:更新主表记录的主键值,如果子表中有和主表匹配的记录,则不允许(产生一个错误提示)。此为默认操作(不指定ON UPDATE子句,系统自动采取的操作)。

CASCADE:更新主表记录的主键值,子表中的匹配记录的外键值一起修改。

SET NULL:更新主表记录的主键值,子表中的匹配记录的外键值改为NULL

SET DEFAULT :更新主表记录的主键值,子表中的匹配记录的外键值改为默认值。


参照完整性属于表间规则。对于相关的表,在更新、插入或删除记录时,如果只改其一不改其二,就可能影响数据的完整性:例如,删除父表的某记录后,子表的相应记录未删除,致使这些记录成为孤立记录;修改父表中对应列的值后,子表对应列的值未做相应改变;对于子表插入的记录,父表中没有对应列的值的记录;更改子表的外键值,父表中没有对应列的值的记录。

 

外键约束的例子

先创建一个主表dept

 CREATE TABLE dept

 (

    deptno NUMBER(4) PRIMARY KEY,

    deptname VARCHAR2(20),

    loc VARCHAR(50)

 );

 

在从表中建立外键约束,可以指定也可以不指定约束名。如省略约束名,则系统自动给出一个约束名。

☆建立从表emp_1时未指定约束名

CREATE TABLE emp_1

 (

    empno NUMBER PRIMARY KEY,

    ename VARCHAR2(20) NOT NULL,

    email VARCHAR2(60) UNIQUE,

    sal  NUMBER(5)CHECK(sal>1500),

    deptno NUMBER(4) REFERENCES dept(deptno)   --无名的外键

 );

 

☆建立从表emp_2时指定了约束名

 CREATE TABLE emp_2

 (

     empno NUMBER PRIMARY KEY,

     ename VARCHAR2(20) NOT NULL,

     email VARCHAR2(60) UNIQUE,

     sal  NUMBER(5)CHECK(sal>1500),

     deptno NUMBER(4) CONSTRAINT fk_name2 REFERENCES dept(deptno) --带名的外键

  );

为约束指定恰当的名称,可便于管理约束。外键约束的名称,用作标识,只要是允许的标识符即可,但有人建议将涉及的表标出,如FK_从表名_主表名 FK_主表名_从表名。

顺便指出,在定义外键时,如果被引用的列是主表中的主键,可以省略被引用的列。如上例中REFERENCES dept(deptno),因为被引用的列deptno是主表dept的主键,所以也可以写成REFERENCESdept

 

外键(FOREIGN KEY)约束,一般用于引用其他表。 FOREIGN KEY 可以是单列键或多列键。以下示例显示 SalesOrderHeader表上引用 SalesPerson表的单列 FOREIGN KEY约束。对于单列 FOREIGN KEY约束,只需要 REFERENCES子句。

SalesPersonID int NULL

REFERENCES SalesPerson(SalesPersonID)

 

也可以显式使用 FOREIGN KEY子句并复述列特性。请注意,在这两个表中列名不必相同。

FOREIGN KEY (SalesPersonID) REFERENCESSalesPerson(SalesPersonID)

 

多列键约束作为表约束创建。 AdventureWorks2012数据库中,SpecialOfferProduct表包含多列 PRIMARY KEY以下示例显示如何从其他表中引用此键(可选择显式约束名)。

CONSTRAINT FK_SpecialOfferProduct_SalesOrderDetail

FOREIGN KEY (ProductID, SpecialOfferID)

REFERENCES SpecialOfferProduct (ProductID,SpecialOfferID)

 

如果仅包含一列可以使用列约束(列级约束),也可使用表约束(表级约束);如果包含两列或更多列,就必须使用表约束。列级约束可在定义列时指定。对于列级外键约束只需要 REFERENCES子句;对于表级外键约束使用FOREIGNKEY REFERENCES子句指定。

 

列约束表约束

约束的类型:PRIMARY KEY(主键)约束、FOREIGN KEY(外健)约束、UNIQUE(唯一)约束、NOT NULL(非空)约束、CHECK(检查)约束、DEFAULT(默认)约束。

当约束被定义于某个表的一列时称为列约束,定义于某个表的多列时称为表约束。当一个约束中必须包含一个以上的列时,必须使用表约束。

 ·什么约束可以实现需要的数据完整性:不同的约束提供了不同的功能。       

 ·在什么时候实施约束最合适:SQLserver允许推迟或者禁用某些已经定义的约束。

 

外键(FOREIGN KEY)约束,也可引用同一表中的其他列。此行为称为自引用。引用的列在同一个表中,而非在另一个表中,这是可以的,虽然这种情况不常见。

create table Course

(

 Cnochar(4) primary key,

 Cname char(40),

 Cpno char(4) references Course(Cno),   --指定自引用

 Ccredit smallint

);

create table Course

(

 Cnochar(4) primary key,

 Cname char(40),

 Cpno char(4),

 Ccredit smallint,

 foreign key (Cpno) references Course(Cno)   --指定自引用

);

 

创建外键约束时需要遵守的原则:

  1. 被外键引用的主表(父表、被参照关系、被引用表、被参照表referenced_table、主键表)中的列名必须是主表中的候选键——主键或已建立UNIQUE约束,一般推荐用主键。简单的说,被外键引用的列必须是主表中的主键或唯一约束,通常是主键。

  2. 外键约束分为列级和表级约束。列级约束只能包含一列。表级约束可以包含一列或多列。

  3. 从表(子表、参照关系、引用表、参照表Referencing table、外键表)的外键的列数和主表中对应的列数必须相同,对应列的数据类型也必须相同,但对应列的名称不必相同。

     

    关系(联系relationship在数据库中指不同表之间的数据彼此联系的方法。可分为3类:一对一、一对多、多对多。

    有表A和表B两个表,如果表A中的一条记录与表B中的一条记录相匹配,反之也是一样,那么这两个表存在一对一关系(one-to-manyrelationship)如果表A中的一条记录与表B中的多条记录相匹配,表B中的一条记录只与表A中的一条记录相匹配,则这两个表存在一对多关系(one-to-manyrelationship)如果表A中的多条记录与表B中的多条记录相对应,且表B中的多条记录也与表A中的多条记录相对应,则称表A与表B多对多关系(many-to-manyrelationship)

    每种关系都有一些变体,如一对一关系,若允许一方为Null着话,可以有零或者一对一关系。

     

    创建一对一关系    两个表的公共字段都必须具有唯一索引,将一个表的公共字段设置为主键或唯一约束,将另一个表的公共字段设置外键。

    公共字段(相关字段、匹配字段、对应列),其名称在两个表中一般相同,也可不同,但要求是相同或相容的数据类型。

     

    创建一对多关系    “一方”表的公共字段必须具有唯一索引。“多方”表的公共字段不应具有唯一索引。它可以有索引,但必须允许重复。将“多方”表的公共字段设置外键。

     

    多对多关系不能直接建立,需要创建第三个表,形成两个一对多关系,第三个表称为“联接表[junction table]”或“链接表[linkingtable]”(有时也称为“Bridge TableJoin TableMap Table”,中间表,是一个包含两个表的公用字段的表(你可以根据实际需要决定是否包括其他字段),它是与其它两个表构成的“一对多”关系的“多方”,也就是两个主表的每一个和联接表定义了一对多关系。

    假设有两个“多对多”表TATB,表TA的主键为a,表B的主键为b,则需要创建第三个表,将ab放入第三个表中设置成该表的外键,建立两个一对多关系:

  1. TA为主表,为“一方”,第三个表是子表,为“多方”。

  2. TB为主表,为“一方”,第三个表是子表,为“多方”。

    [ 第三个表中的外键还可以设置成该表的主键]

        例如,公司有多种类型的计算机和多名技术员,每名技术员均经认证负责部分(非全部)计算机。每名技术员与多台计算机发生关联,而每台计算机相应地与多名技术员发生关联。若要跟踪谁负责指定的计算机,请创建多对多关系,即将关系双方的主键添加至第三个表(计算机技术人员)中,该表称为“联接表”或“链接表”。

    “计算机技术人员”表(“联接表”、子表、“多方”)通过其外键“计算机ID”引用“计算机”表(主表、“一方”)。

    “计算机技术人员”表(“联接表”、子表、“多方”)通过其外键“技术人员ID”引用“技术人员”表(主表、“一方”)。

     

    学习数据库知识时,常常遇到下面这些术语,尽早了解可能更好的减少学习过程中的困惑误解。特地归纳整理如下(每一行作为同义词使用):

关系理论中称谓

概念模型(如E-R模型)中的称谓

ISO SQL标准或一般表格中称谓

传统称谓(源自传统的数据处理)

关系(Relation

实体集(Entity Set实体(Entity[]

表(Table

文件(File

属性(Attribute

属性(Attribute

列(Column

字段(Field

元组(Tuple

实体(Entity实体实例(Entity instance []

行(Row

记录(Record

[]一些文献中的“实体”(Entity)含有集合义等同于另一些文献中的“实体集”(EntitySet),含有个体义的“实体”称为“实体实例”(Entity instance)。实体实例(Entity instance)是实体类型的一个实例,对应于数据表中的一个记录。

关系(Relation)是笛卡尔积的有限子集,形象地说是一个表(二维样式的表),表的每行对应一个元组(Tuple),表中的列称为属性(Attribute)


 



猜你喜欢

转载自blog.csdn.net/cnds123/article/details/39827049
今日推荐