外键用来在两个表的数据之间建立链接,它可以是一个列或者是多列。一个表可以有一个或多个外键。外键对应的是参照完整性,一个表的外键可以为空,若不为空,则每一个外键值必须等于另外一个表中的主键的某个值。
注意!本章节篇幅相对较长,因为该约束对初学者来说,也是表约束中比较难理解和操作的,期间还有坑。请务必仔细阅读和理解!外键约束也会是未来实际工作中经常使用到的重要表约束。
命令格式:[CONSTRAINT[symbol]]FOREIGNKEY[index_name](col_name,…)REFERENCEStbl_name(col_name,…)[ONDELETEreference_option][ONUPDATEreference_option]reference_option:RESTRICT
CASCADE
SETNULL
NOACTION
SETDEFAULT
以上是完整的官方命令格式,看着都晕呀。
[CONSTRAINT外键名]FOREIGNKEY字段名[,字段名2,…]REFERENCES主表名主键列1[,主键列2,…]
以上是国内很多技术数据和网站上摘抄的格式。看还是晕!没事,我们一个一个问题来解决。
建立外键约束的一个要点:首先,需要有主表和从表的概念。简单的理解是父与子的关系。老子有了,儿子才可以有。如果儿子要加入新的信息,必须先问老子有没有,有才可以添加,没有就不可以!稍微理解一点了吗?其次,外键约束是在子表中建立。再次,外键约束的字段,数据属性必须一致。最后,删除外键约束后的数据表,才能被删除。
案例:建立Master、slave2个主、从数据表。建立外键约束并查看录入数据的结果。1:借用guest1和user1数据表的格式,建立Master和slave数据表。2:查看Master和slave数据表结构。3:调整Master数据表结构,完成单主键约束设置,并且输入测试数据。4:调整slave数据表结构,完成外键约束设置,并且输入测试数据。
mysqlCREATETABLEMaster(cust_idint(11),cust_namechar(50));QueryOK,0rowsaffected(0.01sec)mysqlCREATETABLEslave(cust_idint(11),cust_nameint(11),cust_emailchar(),cust_addresschar(50));QueryOK,0rowsaffected(0.04sec)
建立Master和slave数据表。
mysqlDESCMaster;+———–+———-+——+—–+———+——-+
Field
Type
Null
Key
Default
Extra
+———–+———-+——+—–+———+——-+
cust_id
int(11)
YES
NULL
cust_name
char(50)
YES
NULL
+———–+———-+——+—–+———+——-+2rowsinset(0.04sec)mysqlDESCslave;+————–+———–+——+—–+———+——-+
Field
Type
Null
Key
Default
Extra
+————–+———–+——+—–+———+——-+
cust_id
int(11)
YES
NULL
cust_name
int(11)
YES
NULL
cust_email
char()
YES
NULL
cust_address
char(50)
YES
NULL
+————–+———–+——+—–+———+——-+4rowsinset(0.06sec)
查看Master和slave数据表结构。请注意!Master和slave表中都用同一个cust_name字段。不同的是,数据类型。
这里需要告诉大家,为什么?我们需要约束的是slave数据表的cust_name字段,调用的是Master数据表的cust_id字段(该字段是在Master数据表中将要做成主键约束)。本案例中,需要做的是外键约束,条件是约束的字段属性必须一致。
mysqlDROPTABLEMaster;QueryOK,0rowsaffected(0.00sec)
删除Master数据表。
mysqlCREATETABLEMaster(cust_idint(11),cust_namechar(50)NOTNULL,PRIMARYKEY(cust_id));QueryOK,0rowsaffected(0.01sec)
重建Master数据表,为cust_id字段设置单主键设置。
mysqlDESCMaster;+———–+———-+——+—–+———+——-+
Field
Type
Null
Key
Default
Extra
+———–+———-+——+—–+———+——-+
cust_id
int(11)
NO
PRI
NULL
cust_name
char(50)
NO
NULL
+———–+———-+——+—–+———+——-+2rowsinset(0.03sec)
查看Master数据表结构。
mysqlINSERTINTOmaster(cust_id,cust_name)VALUES(‘1’,‘zhangsan’),(‘2’,‘lisi’),(‘3’,‘zhouwu’),(‘4’,‘zhengwang’),(‘5’,‘wangwu’),(‘6’,‘zhaoliu’);QueryOK,6rowsaffected(0.00sec)Records:6Duplicates:0Warnings:0mysqlSELECT*FROMmaster;+———+———–+
cust_id
cust_name
+———+———–+
2
lisi
1
zhangsan
3
zhouwu
4
zhengwang
5
wangwu
6
zhaoliu
+———+———–+6rowsinset(0.04sec)
插入6条测试数据,并且显示。以上操作,master主表(父表)准备完成。
mysqlDROPTABLEslave;QueryOK,0rowsaffected(0.00sec)
删除从表slave。
mysqlCREATETABLEslave(cust_idint(11),cust_nameint(11),cust_emailchar(),cust_addresschar(50),PRIMARYKEY(cust_id),CONSTRAINTcall_nameFOREIGNKEY(cust_name)REFERENCESmaster(cust_id));QueryOK,0rowsaffected(0.04sec)
重新创建slave数据表。注意!cust_name字段熟悉为int(11),与master数据表的cust_id字段熟悉一致。给改表cust_id字段主键熟悉。重点来了!CONSTRAINTcall_nameFOREIGNKEY(cust_name)REFERENCESmaster(cust_id)以上这条语句是外键创建的重点。其中:CONSTRAINT为固定结构的开始。call_name是可以自己可以定义的名称,也是这个外键约束的键名称。FOREIGN是固定结构。KEY(cust_name)中,key是指定键格式,()括号中为本表内建立的与外键相对于的字段名称。案例中指定的是子表中(本表)的cust_name字段。REFERENCES是固定格式。master(cust_id)指定外键的父表名称,案例中是定父表为master数据表。()中输入的是,父表内的指定字段名称,案例中是定父表内的cust_id字段。
mysqlDESCslave;+————–+———–+——+—–+———+——-+
Field
Type
Null
Key
Default
Extra
+————–+———–+——+—–+———+——-+
cust_id
int(11)
NO
PRI
NULL
cust_name
int(11)
YES
MUL
NULL
cust_email
char()
YES
NULL
cust_address
char(50)
YES
NULL
+————–+———–+——+—–+———+——-+4rowsinset(0.05sec)
使用DESC命令,查看slave数据表结构。可以看到,slave数据表中,cust_name字段Key的熟悉现在为MUL。以上案例实验中的,slave建立完成。
继续案例实验按照案例实验的方案,我们将继续往slave数据表中输入数据。因为已经做了外键约束,理论上,再往slave数据中的cust_name字段输入Master数据表cust_id字段中没有的信息,系统将报错。即,在slave数据中的cust_name字段输入1-6之间的数据。系统可以接受,而输入意外的数据,系统不能接受后报错!
mysqlSELECT*FROMmaster;+———+———–+
cust_id
cust_name
+———+———–+
2
lisi
1
zhangsan
3
zhouwu
4
zhengwang
5
wangwu
6
zhaoliu
+———+———–+6rowsinset(0.04sec)
Master数据表cust_id字段中的数据。
mysqlINSERTINTOslave(cust_id,cust_name,cust_email,cust_address)VALUES(‘1’,‘1’,‘
qq.