🚀 个人主页 极客小俊
✍🏻 作者简介:程序猿、设计师、技术分享
🐋 希望大家多多支持, 我们一起学习和进步!
🏅 欢迎评论 ❤️点赞💬评论 📂收藏 📂加关注
浅谈FOREIGN KEY 外键约束
说到FOREIGN KEY 约束
这个东西就有点特殊了, 它个跟我们表与表之间的关系是有 联系的!
比如
一个表中的 FOREIGN KEY 约束字段
通常会指向另一个表中的 PRIMARY KEY主键字段
FOREIGN KEY 约束
的作用是预防破坏表与表
之间连接的动作,也能防止非法数据插入外键字段, 因为它必须是它指向的那个表中的值之一~!
这样说可能大家还有点不是很理解,其实FOREIGN KEY约束
是数据库中用于确保数据一致性和完整性的一种重要机制
首先我们要理解一下表的定义与关系
以及外键
的基本含义
外键
外键
在我们这里其实就是FOREIGN KEY约束
我们平常简称FK
, 是表
中的一个
或多个字段
,注意这些字段的值依赖于另一个表, 通常称为主表
或父表
, 而值就是主表中的主键
或唯一键
的值
关系
我们通过外键
,我们可以在两个表之间建立一种父子
关系,也就是说外键
所在的表称之为子表
或从表
, 它依赖于外键
所引用的表, 我们称之为: 主表
或父表
FOREIGN KEY约束 场景描述
从我们的实际应用场景来说我们可以看做是如下案例:
员工与部门
:
假设有两个表,一个是员工表(子表)
命名为Employee
,另一个是部门表(主表)
命名为dep
那么此时此刻,我们可以把员工表
中的部门ID字段
可以设置为外键FOREIGN KEY约束
,引用部门表中的主键id字段
,从而建立员工
与部门
之间的关联关系, 这样建立了从属关系!
所以首先你要知道谁属于谁, 那么你就明白FOREIGN KEY约束
是建立在哪个表中了!
其实你可以这样想, 在SQL
中 FOREIGN KEY约束
存在于哪个表,那么那个表就是子表
!
语法规则
在子表
建立的时候,执行以下规则:
子表字段名称 int,
FOREIGN KEY (子表字段名称) REFERENCES 主表名(主表字段名称)
员工与部门数据场景描述
语法解释如下
这里的子表字段名称
是指我们想要设置为外键
的字段,它子表中, 而主表名
和主表字段名称
则分别指的是外键
所引用
的父表
的名称和该表中的字段名称
,该字段通常是主键
或唯一键
那么如果从SQL代码建立表的角度来说,代码如下:
CREATE TABLE dep(
department_id int PRIMARY KEY,
dep_name VARCHAR(100)
)
CREATE TABLE employees (
id int PRIMARY KEY,
username VARCHAR(100),
department_id int,
FOREIGN KEY (department_id) REFERENCES dep(department_id)
)
我们在SQL Server 2000
中来执行以下看看效果!
如图
我们要注意一点,FOREIGN KEY约束
通常不是单独使用的,而是作为CREATE TABLE
语句或ALTER TABLE
语句的一部分进行使用!
在这个例子中,Employee表
的department_id字段
被设置为外键
,它引用了dep
表的id主键字段
那现在你可能会想,这样做的目的又是什么呢?
这样做有几个关键的作用和好处:
1.数据一致性
:
外键约束
确保了Employee员工表
中的每一条记录都指向dep部门表
中存在的一个有效部门
那么这意味着,我们不能在Employee员工表
中随意插入一个department_id
,如果要插入那么department_id
必须要在dep部门表
中存在才可以进行插入!~ 否则会报错!
如图
效果如图
这就有助于维护数据的一致性,防止出现孤立的、无法与部门
对应的员工记录
了!
2.数据完整性
外键约束
还可以防止dep(部门表)
中的部门信息
被意外删除
或修改
,从而影响到Employee员工表
中的相关记录。
也就是说外键约束
会阻止我们删除
或修改
那些仍然被Employee表
引用的部门记录,从而维护了数据的完整性。
如图
3.FOREIGN KEY约束也可以进行查询优化
:
虽然FOREIGN KEY约束
本身并不直接优化查询性能,但它通过明确表之间的关系,使得数据库优化器
能够更有效地执行JOIN
等查询操作, 这是因为数据库知道哪些字段是相关的,并可以利用这些关系来减少需要扫描的数据量。
4.从业务逻辑表达方面
FOREIGN KEY约束
是数据库层面上的业务逻辑表达, 它告诉数据库系统, 表与表
之间存在一种特定的关系,这种关系对于应用程序的业务逻辑来说是至关重要的。通过FOREIGN KEY约束
,数据库能够自动地强制执行这种关系,而不需要在应用程序代码中显式地编写额外的逻辑来维护它
5.数据建模方面
在数据库设计和建模过程中,FOREIGN KEY外键约束
是表达实体之间关系的一种重要方式。
这样我们可以清晰地看到哪些实体是相互关联的,以及它们是如何关联的。
这对于理解数据库的结构、设计数据库查询以及维护数据库的一致性都是非常重要的!~
如图
订单与商品数据场景描述
再举个梨子:订单与商品
的应用场景, 这个场景是我们实际开发中经常会遇见到的!
在订单管理系统
中,订单表
和商品表
之间也可以通过外键建立关联
,确保订单
中引用的商品
确实存在于商品表
中。
所以我们首先要梳理清楚这种关系层面, 我们才好去建立 FOREIGN KEY外键关系
知道谁是主表(父表)
谁又是从表(子表)
在这个场景下很明显我们的商品表
是主表
,而订单表
是从表
, 以确保订单
中引用的商品
确实存在于商品表
中!
例如
场景描述
在订单管理系统中,通常有以下几个关键实体:
商品表Product
:代表可购买的物品或服务,每个商品有唯一的标识, 比如: 商品id
订单表order
: 代表客户购买的一组商品,每个订单包含多个订单项
, 每个订单项
关联到一个具体的商品
和购买数量
实体关系描述
商品表Product
:作为主表(父表)
,存储商品
的基本信息字段,比如: 商品ID(主键)、商品名称、价格
等。
订单表 Order
:作为从表(子表)
,存储订单
的基本信息,比如: 订单ID(主键)、下单时间、客户信息
等。
但是通常情况下订单表
本身不直接存储商品信息
,而是通过订单项
与商品表
建立关联, 所以这里我们多建立一个订单项表OrderItem
订单项表OrderItem
:来作为连接订单表
和商品表
的桥梁,
也就是说每个订单项
包含订单ID(外键,引用订单表的主键)、商品ID(外键,引用商品表的主键)和购买数量等信息
。
这样,一个订单
可以包含多个订单项
,每个订单项
都关联到一个具体的商品。
注意: 在这里订单
和商品
之间并不是直接的多对多关系
,而是通过订单项表
来实现的一对多
和多对一
的组合关系。
外键关系
那么我们就可以在订单项表
中,会有两个外键:order_id
和product_id
order_id
是外键
,引用订单表
的order_id字段(主键)
,表示该订单
项属于哪个订单
product_id
是外键
,引用商品表
的product_id字段(主键)
,表示该订单项
对应哪个商品
表的建立
建立FOREIGN KEY外键关系
在创建数据库表时,我们需要在这两个外键字段
上设置外键约束
,以确保数据
的一致性
和完整性
那么创建商品表、订单表、订单项目表
在SQL
中我们可以如下方式:
商品表
CREATE TABLE Product( /*创建商品表*/
pid int PRIMARY KEY IDENTITY,
pname varchar(20),
price varchar(20)
)
订单表
CREATE TABLE Orders( /*创建订单表*/
oid int PRIMARY KEY IDENTITY,
times varchar(20)
userinfo int
)
注意:
假设userinfo 字段
用户ID ,那么这里很可能会把userinfo字段
设置为外键
, 还需要添加外键约束
, 这里我们就不多说了!
订单项目表
CREATE TABLE OrderItem ( /*创建订单项目表*/
order_id INT PRIMARY KEY IDENTITY,
oid INT,
pid INT,
FOREIGN KEY (oid) REFERENCES Orders(oid),
FOREIGN KEY (pid) REFERENCES Product(pid)
)
如图
那么我们现在就可以来添加数据测试一下!
我们结合上图一起来捋一捋关系具体来说:
一个订单(Order)
可以包含多个订单项(OrderItem)
,每个订单项
代表订单中
的一个商品
及其数量,对吧!
这是一对多
的关系,因为一个订单对应多个订单项
, 其实你可以理解这实际上就相当于一个订单
对应了多个商品
,因为每个订单项都代表了订单中的一个具体商品及其购买数量。
反过来想一个订单项OrderItem
只属于一个订单Order
,并且只对应一个商品(Product)。
这是多对一
的关系,因为多个订单项可以属于同一个订单,但每个订单项只对应一个商品。
然而,当我们从另一个角度看时,即商品
与订单项
之间的关系,以及订单项
与订单
之间的关系结合起来考虑,可以说商品
与订单
之间存在一种多对多
的潜在关系,但这种关系并不是直接的,而是通过订单项
作为中介来实现的。
一个商品可以被多个订单项引用,也就是说多个订单可能包含同一个商品。
同时,一个订单(Order)可以包含多个不同的商品,
因此,虽然订单
和商品
之间不是直接的多对多关系,但它们之间确实存在这种潜在的、通过订单项表间接实现的多对多关系。在实际应用中,我们通常通过维护订单项表来管理这种复杂的关系,确保数据的准确性和一致性,同时也在适当的时候设置FOREIGN KEY外键约束
从这里的场景来说,我们会先有商品表(主表)
然后再有订单表
,最后才是订单项目表
所以我们有了FOREIGN KEY外键约束
就不会存在 乱加数据 破坏数据的一致性和稳定性!
我们通过SQL查询
可以来查看具体我们每一个订单对应哪些商品, 以及对应的用户
select Orders.oid,Product.pid,Product.price,Product.pname,Orders.userinfo
from OrderItem
INNER JOIN Orders ON OrderItem.oid = Orders.oid
INNER JOIN Product ON OrderItem.pid = Product.pid
WHERE Orders.userinfo = 1;
如图
比如我要查询用户ID
为1的对应有哪些订单,以及商品
如图
修改FOREIGN KEY外键约束
如果在表已存在的情况下要给某个字段创建 FOREIGN KEY 约束
并且带有外键约束命名, 那么语法如下:
ALTER TABLE 表名称 ADD CONSTRAINT 外键约束名称 FOREIGN KEY (子表字段名称) REFERENCES 主表名称(主表字段名称)
我们来测试一下!
如图
CREATE TABLE Product( /*创建商品表*/
pid int PRIMARY KEY IDENTITY,
pname varchar(20),
price varchar(20)
)
CREATE TABLE Orders( /*创建订单表*/
oid int PRIMARY KEY IDENTITY,
times varchar(20),
userinfo int
)
CREATE TABLE OrderItem ( /*创建订单项目表*/
order_id INT PRIMARY KEY IDENTITY,
oid INT,
pid INT
)
然后修改OrderItem 表
中的oid
和pid
字段
ALTER TABLE OrderItem ADD CONSTRAINT fk_oid FOREIGN KEY (oid) REFERENCES Orders(oid);
ALTER TABLE OrderItem ADD CONSTRAINT fk_pid FOREIGN KEY (pid) REFERENCES Product(pid);
如图
我们可以在企业管理器
中去查看外键约束
的关系图
如图
删除FOREIGN KEY外键约束
如需撤销 FOREIGN KEY 约束
我们最好根据创建外键约束的时候,命名的名字来进行删除!
ALTER TABLE 表名称 DROP CONSTRAINT 外键名称
如图
这时候,我们回到企业管理器中查看表关系,就会自动取消 彼此之间的约束联系了!
如图
关于表与表
之间的关系和SQL查询
的方法以及如何使用INSERT UPDATE 和DELETE
语句来处理数据 ,我会在接下来的章节再和大家 慢慢详谈!
"👍点赞" "✍️评论" "收藏❤️"
欢迎一起交流学习❤️❤️💛💛💚💚
好玩 好用 好看
的干货教程可以
点击下方关注❤️
微信公众号❤️
说不定有意料之外的收获哦..🤗嘿嘿嘿、嘻嘻嘻🤗!
🌽🍓🍎🍍🍉🍇