文章目录
- 1. 关系数据库外键概念理论(大学时学习的概念)
- 1.1 实体完整性
- 1.2 ✅ 参照完整性
- 1.3 用户定义完整性
- 1.4 ✅ 参照完整性的SQL实现
- 1.5 ✅ MySQL数据库操作示例
- 1.6 ✅ neo4j中的关系和mysql的外键
- 2 MySQL中实现的规定
- 2.1 基本概念
- 2.2 ✅ 命名规则
- 2.3 ✅ 条件和限制
- 2.3.1 存储引擎查询
1. 关系数据库外键概念理论(大学时学习的概念)
教材是:王珊,萨师煊老师的数据库系统概论——第五版,这里直接丢截图了。
- 有三类完整性约束,分别是:实体完整性、参照完整性以及用户定义的完整性。
- 其中实体完整性和参照完整性是关系模型必须满足的完整性约束条件,被称作是关系的两个不变性,应该由关系系统自动支持(例如MySQL要负责这部分约束的检查)
- 用户定义的完整性是应用领域需要遵循的约束条件,体现了具体领域中的语义约束
- 不做强制检查,最多让人感觉不符合现实或者有点蠢,和程序员不怎么相关😛😛😛
- 比如:成绩只能是0-100,年龄只能是0-150以内,生日只能是1.1-12.31,类似这种语义约束。
1.1 实体完整性
主要用来描述,数据库中每行数据都应该是可区分的(有某个属性是唯一的!)
1.2 ✅ 参照完整性
- 参照完整性用来描述实体和实体间的联系(可以认为就是图数据库中的关系/边,relationship)
- 可以参考:图数据库初探——4. mysql数据导入neo4j(desktop界面导入)中💫
2.3 关系数据库转为图数据库的规则
部分。
- 可以看到,数据库理论中
- 假如
F
属性是一个表R
的属性,但是不是主码;属性K
是表S
的主码。(表R
和表S
不一定是不同的表)。如果F
和K
对应,则称F
是表R
的外码,并称表R
是参照关系(参照表),表S
是被参照关系。 - 可以去看看
1.5 MySQL数据库操作示例
- 这里的参照完整性规则,意思就是:如果选课表中的课程id,参照了课程表中的课程id,
- 那么选课表中的课程id的取值,要么为空,要么就等于 课程表中的课程id中某个值。
也是:Mysql错误1452 - Cannot add or update a child row: a foreign key constraint fails怎么办?中这个回答的理论依据。
1.3 用户定义完整性
1.4 ✅ 参照完整性的SQL实现
还是王珊,萨师煊老师的教材,是后面的例子,截图贴上来
主要还是关于参照完整性(外键)这部分的内容
可以看到,对于学生版Student(Sno)、课程表Course(Cno)和学生选课表SC(Sno,Cno)来说,按照上面的规定,
则,Sno是表SC的外码,SC表是参照关系,被参照表是Student;Cno也是表SC外码,SC表是参照关系,被参照表是Course。
1.5 ✅ MySQL数据库操作示例
如果是用Navicat设计mysql数据库,那么可视化应该是这样:
例如,有两个表,分别是poem(诗表)和poet_to_poem(诗人和诗对应表)
poem(诗表)数据
poet_to_poem(诗人和诗对应表)数据
poem(诗表)非空和主键约束
poet_to_poem(诗人和诗对应表)非空和主键约束
很明显,poet_to_poem
表中的poem_id
是引用自poem
表,所以可以设置一个外键(对poet_to_poem表设置)。
所以外键是设置在引用了其他表字段的表上!
设置完之后,ER图显示就是这样,主键是钥匙,外键是个锁扣的形状
1.6 ✅ neo4j中的关系和mysql的外键
之前在:图数据库初探——4. mysql数据导入neo4j(desktop界面导入)中,由于外键设置错误,所以导入的时候,只导入了节点,没有识别出关系。设置正确后,就可以正确识别关系了,如下:
C:\shaiic_work\neo4j_data\relate-data\dbmss\dbms-54e8721d-3337-412a-8b54-d6ccd03b564e\bin\neo4j-admin.bat @C:\Users\HUANGS~1\AppData\Local\Temp\csv-001\neo4j-admin-import-params
很奇怪,这个命令运行了两次,第一次报错了
另外,重启桌面版之后,这个新建的数据库在对应的DBMS界面没有显示,但是用命令行去看,是可以看到的。
CALL db.schema.visualization()
可以看到,neo4j中的schema导入前mysql的schema是基本一致的(只是关系表,转为了relationship边)
match (p:Poem)
return p
一个表的主码就作为节点,其他的属性就作为节点的属性。
2 MySQL中实现的规定
根据参考,进行关键部分的摘录
2.1 基本概念
MySQL支持外键,允许跨表的交叉引用(外键可以是表内,也可以是表外,mysql都支持),外键约束可以帮助保持相关数据的一致性。(被参照表的主键字段删了,对应的参照表的外键也会删掉)
外键关系包含拥有列的初始值的父表(例如:学生表),以及引用父表中列的值的子表(例如:学生成绩表引用学生表的student_id)。外键约束定义在子表上
创建表或者修改表时进行外键约束的语法如下(只有这两种时候才可以加外键约束):
[CONSTRAINT [symbol]] FOREIGN KEY
[index_name] (col_name, ...)
REFERENCES tbl_name (col_name,...)
[ON DELETE reference_option]
[ON UPDATE reference_option]
reference_option:
RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT
2.2 ✅ 命名规则
- 在外键约束的语法中,如果已经对外键命名,即上面的
[CONSTRAINT [symbol]] FOREIGN KEY
中symbol
这个字段有值了,则直接使用这个值作为外键名称 - 如果CONSTRAINT symbol子句未定义,或CONSTRAINT关键字后未包含符号,
- 对于InnoDB表,会自动生成约束名称,ibfk是InnoDB Foreign Key的缩写
- 例如:使用Navicat工具管理mysql数据库。外键的一种常用命名方式是
表名_fk_序号
,如下,poet表的第一个外键就是:poet_ibfk_1
- 对于NDB表,使用该 FOREIGN KEY index_name值(如果已定义)。否则,会自动生成约束名称。
- 该值(如果已定义)在数据库中必须是唯一的。重复会 导致类似于以下内容的错误:
ERROR 1005 (HY000): Can't create table 'test.fk1' (errno: 121)。 CONSTRAINT symbolsymbol
(外键名称在一个数据库中必须唯一)
这是Mysql错误1452 - Cannot add or update a child row: a foreign key constraint fails怎么办?这个错误下这个答案的依据,只是不太匹配这个报错信息
2.3 ✅ 条件和限制
外键约束遵循以下条件和限制:
-
父表和子表必须使用相同的存储引擎,同时子表和父表不能是临时表。
- 这是Mysql错误1452 - Cannot add or update a child row: a foreign key constraint fails怎么办?这个错误下这个答案的依据
-
创建外键需要从父表得到 REFERENCES 权限(需要有引用的权限)
-
外键列和它引用的被参照列必须有相似的数据类型(最好是一模一样或者是可以兼容的),比如整数(INTEGER)和小数(DECIMAL)的符号以及固定精度必须一致;如果是字符串类型,则对长度的规定可以不一致,对于非二进制(字符)字符串列,字符集和排序规则必须相同。
- 类似下面这样
-
MySQL支持外键引用同一个表中的另一列(主键),但是列不能对列自身有引用。在这种情况下,子表记录指的是同一个表中的依赖记录。
- 比如,如果学生组,包含学生id属性,小组长/班长id属性,那么后者其实就会引用前者,所以支持同一个表中不同列的引用,但是不支持列对列自身的引用
-
MySQL要求外键和引用的列上都有索引,这样进行外键检查的时候就不需要扫描整个表,可以加快速度。在引用表中,外键引用的那列必须要用索引,如果没有,就会自动创建。
-
对于InnoDB来说,允许外键引用含有索引的列或者列组(好几列),不过,在引用的数据表上,其中引用的第一列上必须有相同的索引。
- 关于索引这部分,其实可以观察一下,在创建外键之后,会自动对外键的列添加索引。(确实是引用表的外键上有索引,被引用的则没有)
- 关于索引这部分,其实可以观察一下,在创建外键之后,会自动对外键的列添加索引。(确实是引用表的外键上有索引,被引用的则没有)
-
外键关系中的表不能更改为使用另一个存储引擎。要更改存储引擎,您必须首先删除所有外键约束。简单来说,还是建立外键关系的两个表,必须使用同一种存储引擎
2.3.1 存储引擎查询
- 关于存储引擎,其实就是这个:
- 也可以使用sql语句查询某个表的存储引擎
# 查询某个数据库中所有表的存储引擎 show table status from 库名; # 查询某个特定表的存储引擎 show table status from 库名 where name='表名';
参考:
- mysql官方文档:13.1.18.5 FOREIGN KEY Constraints
- mysql官方文档:1.7.2.3 FOREIGN KEY Constraint Differences
✅mysql5.7文档中文翻译(显示的是5.7 但是对应章节都不一样,参考对照着看,另外,有点像机翻,哈哈。)
-
13.1.18.5 外键约束
-
1.8.2.3 FOREIGN KEY 约束差异
-
MySQL自学笔记——设置外键约束这个应该也是看官方文档翻译的,可以作为参考
其他可能有用的信息
- SQL FOREIGN KEY 约束
- MySQL外键约束(FOREIGN KEY)
mysql5.1文档的中文翻译
- 1.8.6. MySQL处理约束的方式,网页中的链接有错误,自己往下拉,或者直接搜索
外键
- 15.2.6.4.外键约束
- 23.1.12. INFORMATION_SCHEMA TABLE_CONSTRAINTS表
实践的结果(从程序员的角度来看):
- 父表中的非主键 可以作为子表外键吗? 理论依据何在?
- 一个表的字段不是主键可以做其他表的外键么
更多推荐
数据库外键理论及MySQL外键实现规定
发布评论