【postgresql 基础入门】表的约束(一)主键与外键,数据的实体完整性与参照完整性,外键引用数据被修改时的动作触发
主键与外键-表的约束(一)
专栏内容:
- postgresql内核源码分析
- 手写数据库toadb
- 并发编程
个人主页:我的主页
管理社区:开源数据库
座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物.
系列文章
- 入门准备
- postgrersql基础架构
- 快速使用
- 初始化集群
- 数据库服务管理
- psql客户端使用
- pgAdmin图形化客户端
- 数据库的使用
- 创建数据库
- 数据库操作
- 表的使用
- 表的创建
- 表的操作
- 数据查询
- 数据查询
- 多表联合查询
- 数据操作
- 插入数据的方式
文章目录
- 主键与外键-表的约束(一)
- 系列文章
- 一、概述
- 约束的定义
- 约束的分类
- 二、主键约束
- 定义主键约束
- 修改添加主键约束
- 删除主键约束
- 三、外键约束
- 定义外键约束
- 修改表添加外键约束
- 删除外键约束
- 自引用外键
- 被引用表的变动影响
- 数据变动
- 表删除
- 四、总结
- 五、结尾
一、概述
在数据库中,数据类型可以限制数据存储的大小,也能在一定程度上限制存储的数据种类,但是对于数据库应用来讲,它太宽泛了,比如有些表示人名的字段,就不能为空,货物数量的字段,不能为负值,这与实际生活符合,而数据类型并不能做这些约束,这就需要数据库提供一套更贴近应用,或者说与现实世界更符合的规则,来约束数据的有效性。
约束的定义
数据库的约束是一种规则,用于限制或规范数据库中的数据,确保数据的完整性和一致性。这些约束可以定义在表级别或列级别,处理机制是一致的。约束不占用任何数据库空间,而是存在于数据字典中,并在执行SQL期间使用。用户可以指明约束是启用的还是禁用的,当约束启用时,它增强了数据的完整性。
约束的分类
postgresql数据库中的约束类型主要包括以下几种:
- 主键约束(Primary Key):主键约束相当于唯一约束和非空约束的组合。它确保表中的每一行数据都有一个唯一标识符,不允许重复,也不允许出现空值。每个表最多只允许一个主键。当创建主键约束时,系统默认会在所在的列或列组合上建立对应的唯一索引。
- 外键约束(Foreign Key):外键约束用于保证一个或两个表之间的参照完整性。它构建于一个表的两个字段或是两个表的两个字段之间的参照关系。
- 唯一约束(Unique):唯一约束要求指定的表列或列组合的值不能重复,保证数据的唯一性。同一个表可以有多个唯一约束。在创建唯一约束时,如果不给唯一约束名称,就默认和列名相同。与主键约束不同,唯一约束允许空值的存在,但只能出现一个空值。
- 非空约束(NOT NULL):非空约束用于确保当前列的值不为空值。它只能出现在表对象的列上。
- 检查约束(Check):检查约束会判断指定的条件是否为true,当为true时符合约束。
- 排除约束(Exclude): 在排除约束指定的表达式返回false或null时,才符合约束。
这些约束在数据库设计中起着至关重要的作用,它们有助于维护数据的准确性和一致性,防止无效数据的插入和更新。
二、主键约束
在表的列上指定一列或几列的组合,创建主键,这一列或列的组合就称为主键列,主键列上的所有行的数据不能重复,同时主键列的值不能为空。
在每个表上只能最多有一个主键。
建议在每张表上都创建一个主键,因为在建立主键的同时,数据库会自动在主键列上创建索引,叫做主键索引,它可以加束通过主键的查找或者修改数据。
下面列举几创建主键的SQL语法有几种形式。
定义主键约束
- 一是在定义列的时候就指定主键,这适合主键列只有一列的情况;
CREATE TABLE table_name (column1 data_type PRIMARY KEY, column2 data_type,…
);
- 另一种是约束定义写在表定义的最后,这适合于主键列包含多列的情况;
CREATE TABLE table_name (column_1 data_type, column_2 data_type,column_3 data_type,…PRIMARY KEY(column_1, column2, ...)
);
不管是主键列有一列或者多列,两种写法都可以使用。
修改添加主键约束
当我们的表已经创建完成时,或者数据已经导入,此时发现需要增加一个主键,那么可以通过修改表定义的方式来添加主键,SQL语法如下:
ALTER TABLE table_name
ADD PRIMARY KEY (column_1, column_2, ...);
当然这个操作需要有表的alter权限。
删除主键约束
有创建主键,就可以删除主键,删除主键约束的SQL语法如下:
ALTER TABLE table_name
DROP CONSTRAINT primary_key_constraint_name;
其中primary_key_constraint_name
是主键约束的名称,在上面的创建方法中,我们并没有指定主键约束的名称,数据库会自动为我们增加主键约束的名称,在删除之前需要通过\d
命令来查看一下表的定义,示例如下:
postgres=# \d productsTable "public.products"Column | Type | Collation | Nullable | Default
--------------+------------------------+-----------+----------+---------product_id | integer | | not null |product_name | character varying(255) | | not null |price | numeric(10,2) | | not null |category | character varying(255) | | |
Indexes:"products_pkey" PRIMARY KEY, btree (product_id)
Referenced by:TABLE "orders" CONSTRAINT "orders_product_id_fkey" FOREIGN KEY (product_id) REFERENCES products(product_id)postgres=#
products
表在product_id
列上有一个主键,名称为products_pkey
,因为它同时会创建索引,所以在索引分类中。
注意,这里有可能会被别的表以外键方式引用,就会删除失败,此时的处理方法请看下一节外键约束。
三、外键约束
当定义一张表时,期望其中一列的数据与另一张表的某一列的数据一致时,就需要用到外键约束,比如定单表中的产品ID列,就需要与产品表中的产品ID列一致,不能出现产品表中没有的产品ID。
外键约束是指一列或几列的值,与另一张表的对应的一列或几列出现的值相匹配,我们说这两张相关表保持了引用完整性。
注意外键通过引用另一张表的唯一能标识行的一列或一组列的值来建立引用关系,所以被引用的列必须是主键的列。当然,引用与被引用的列的类型是必须相同的,也就是它们有相同的值范围。
外键约束的定义SQL语法,同样也有几种。
定义外键约束
CREATE TABLE table_name1 (column11 data_type , column12 data_type REFERENCES table_name2 (column21),…
);
在需要定义引用完整性的列定义后面,使用references
关键字,再加被引用的表外与列名即可。
另一种是放在表定义的最后,可以指定单列或多列的引用完整性。
CREATE TABLE table_name1 (column11 data_type , column12 data_type ,…FOREIGN KEY (column11, column12) REFERENCES table_name2 (column21, column22)
);
放在表定义后部时,需要使用foreign key
关键字开头来指定本表需要引用的字段。
修改表添加外键约束
当数据表创建完成后,可以通过修改表的定义来完成外键的添加;
ALTER TABLE table_name1
ADD CONSTRAINT foreign_key_constraint_name
FOREIGN KEY (column11 ...)
REFERENCES table_name2 (column22 ...);
这里可以是单列,或者多列组的引用。
删除外键约束
当不需要外键约束时,可以删除表上某个外键,外键约束的名称通过查看表定义来获得,在命令行客户端上通过\d tablename
命令查看。
ALTER TABLE table_name1
DROP CONSTRAINT foreign_key_constraint_name;
自引用外键
除了引用另一张表之外,还可以引用自身表的列,这也是非常有用的一种写法。
CREATE TABLE tree (node_id integer PRIMARY KEY,parent_id integer REFERENCES tree,name text,...
);
被引用表的变动影响
因为外键是引用另一张表,当被引用表发生变动时,也会影响引用表,也就是外键表。
一般会发生两类变动:
- 一是被引用表的数据发生变化,当然新增数据不会产生影响,当原有数据被delete删除或update修改时,引用表中正在引用的数据不见了,就会产生错误;
- 二是被引用表要被删除时,也不能直接删除;
数据变动
假如一个订单表的产品ID列引用产品表的ID列,那么会存在这样一个情况,产品不再有效时,会从产品表中删除,那么此时订单表中已经产生的此产品的订单将会如何处理呢?
可能是,不让它删除,这在一些应用中也是如此处理,另外会加一个是否删除的字段;或者把订单表中引用此产口ID的订单一起删除,这看起来不是很好;一起来看看数据库中提供了那些可选项。
在定义外键时,可以指定它的引用数据发生变动时,可以执行的动作,语法如下:
CREATE TABLE table_name1 (column11 data_type , column12 data_type ,…FOREIGN KEY (column11, column12) REFERENCES table_name2 ON DELETE [action] (column21, column22)
);
还可以是,
CREATE TABLE table_name1 (column11 data_type , column12 data_type ,…FOREIGN KEY (column11, column12) REFERENCES table_name2 ON UPDATE [action] (column21, column22)
);
因为被引用表的数据有删除或更新两种情况,在这两种情况下引用表需要指定动作,其中的action可以用以下动作代替:
- NO ACTION, 在没有指定时,默认就是没有动作;也就是在修改和删除被引用表的数据时,会检查是否有引用,如果有引用则会报错,也就是阻止被修改和删除;
- RESTRICT, 与on action类似,会阻上被引用列的修改或删除,但是restrict会将检查延迟处理;
- SET NULL, 将被引用列删除的行,在引用列中置为NULL;
- SET DEFAULT,当被引用列删除时,将引用例置为默认值,这里可以指定在此情况下的默认值;
- CASCADE,级联处理,也就是当被引用列删除时,引用列的所有该值的行会自动删除;
这部分我们将在单独的一个章节点来分享。
表删除
与数据变动有类似的问题,被引用表删除时或者主键删除时,引用表如何处理呢?
在postgresql中,会阻止被引用表的删除,必须先解除引用,或者先删除引用表,这里提供了一个cascade
选项,可以级联删除引用表。
postgres=# \d order_itemsTable "test1.order_items"Column | Type | Collation | Nullable | Default
------------+---------+-----------+----------+---------product_no | integer | | |order_id | integer | | |quantity | integer | | |
Foreign-key constraints:"order_items_order_id_fkey" FOREIGN KEY (order_id) REFERENCES orders(order_id)"order_items_product_no_fkey" FOREIGN KEY (product_no) REFERENCES products(product_no)
查看一下外键关系,可以看到order_items
同时引用了orders
和products
两张表的列,下面选择将products
表删除,并指定级联删除选项;
postgres=# drop table products cascade ;
NOTICE: drop cascades to constraint order_items_product_no_fkey on table order_items
DROP TABLE
postgres=# \dList of relationsSchema | Name | Type | Owner
--------+-------------+-------+--------test1 | order_items | table | zpzhaotest1 | orders | table | zpzhao
(2 rows)
可以看到删除表的同时会自动将引用关系解除,删除了order_items
表上对products
表的外键引用。
四、总结
本文主要分享了表的约束分类中的主键和外键两类,它们对数据的数据的实体完整性和参照完整性都会起到约束作用,当然在使用过程中要熟悉它们的SQL语法,以及它们的特性。
五、结尾
非常感谢大家的支持,在浏览的同时别忘了留下您宝贵的评论,如果觉得值得鼓励,请点赞,收藏,我会更加努力!
作者邮箱:study@senllang.onaliyun.com
如有错误或者疏漏欢迎指出,互相学习。
注:未经同意,不得转载!
相关文章:
【postgresql 基础入门】表的约束(一)主键与外键,数据的实体完整性与参照完整性,外键引用数据被修改时的动作触发
主键与外键-表的约束(一) 专栏内容: postgresql内核源码分析手写数据库toadb并发编程 个人主页:我的主页 管理社区:开源数据库 座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物. 系列文章…...
centos 7 添加启动脚本
centos 7 java 开机启动 在CentOS 7上配置Java应用程序开机启动,可以通过创建一个systemd服务单元来实现。以下是步骤和示例代码: 创建一个新的systemd服务文件。 sudo vi /etc/systemd/system/your-java-app.service 在该文件中添加以下内容ÿ…...

java入门基础掌握知识
Java基础入门 Java一门 高级 编程语言 Java是 sun 公司研发的,现在属于 oracle 公司 Java之父是 詹姆斯.高斯林 Java主要是来做 企业级 应用开发的 Java的三大技术体系是: 技术体系说明Java SE(Java Standard Edition):标准版Java技术的核心和基础…...

Harbor高可用(nginx和keepalived)
Harbor高可用(nginx和keepalived) 文章目录 Harbor高可用(nginx和keepalived)1.Harbor高可用集群部署架构1.1 主机初始化1.1.1 设置网卡名和ip地址1.1.2 设置主机名1.1.3 配置镜像源1.1.4 关闭防火墙1.1.5 禁用SELinux1.1.6 设置时…...
[数据集][目标检测]牛羊检测数据集VOC+YOLO格式3393张2类别
数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):3393 标注数量(xml文件个数):3393 标注数量(txt文件个数):3393 标注…...

命令提示符——CMD基础操作介绍
💞💞 前言 hello hello~ ,这里是大耳朵土土垚~💖💖 ,欢迎大家点赞🥳🥳关注💥💥收藏🌹🌹🌹 💥个人主页&#x…...

vue2 自定义 v-model (model选项的使用)
效果预览 model 选项的语法 每个组件上只能有一个 v-model。v-model 默认会占用名为 value 的 prop 和名为 input 的事件,即 model 选项的默认值为 model: {prop: "value",event: "input",},通过修改 model 选项,即可自定义v-model …...

智慧城市中的智慧生活:便捷、舒适与高效
目录 一、智慧城市中的智慧生活概述 二、智慧生活带来的便捷性 1、智慧交通的便捷出行 2、智慧购物的轻松体验 3、智慧政务的一站式服务 三、智慧生活带来的舒适性 1、智慧环境的绿色宜居 2、智慧医疗的健康保障 3、智慧教育的均衡发展 四、智慧生活带来的高效性 1、…...

时代教育期刊投稿发表
《时代教育》是由成都传媒集团主管主办,中华人民共和国新闻出版总署批准国内公开出版发行的专业教育类期刊,主要刊登各类高等院校、职业技术学校、中小学教师及研究生、教育科研工作者的教育实践研究成果;教育教学行业的最新动态;…...
每日OJ题_子数组子串dp⑥_力扣978. 最长湍流子数组
目录 力扣978. 最长湍流子数组 解析代码 力扣978. 最长湍流子数组 978. 最长湍流子数组 难度 中等 给定一个整数数组 arr ,返回 arr 的 最大湍流子数组的长度 。 如果比较符号在子数组中的每个相邻元素对之间翻转,则该子数组是 湍流子数组 。 更正…...

蓝桥练习题总结(一)字母图形、完美的代价、01串、序列求和
目录 一、字母图形 二、完美的代价 三、01字串 四、序列求和 一、字母图形 问题描述 利用字母可以组成一些美丽的图形,下面给出了一个例子: ABCDEFG BABCDEF CBABCDE DCBABCD EDCBABC 这是一个5行7列的图形,请找出这个图形的规律ÿ…...
Android 静默安装二(无障碍服务版)
近期开发上线一个常驻app,项目已上线,今天随笔记录一下静默安装相关内容。我分三篇静默安装(root版)、静默安装(无障碍版)、监听系统更新、卸载、安装。 先说说我的项目需求:要求app一直运行&am…...

蓝桥杯 EDA 组 2023模拟+真题原理图解析
本文解析了标题内的原理图蓝桥杯EDA组真题,2021-2022 省赛真题/模拟题在上一篇文中。本文中重复或者是简单的电路节约篇幅不在赘述。 其中需要补充和计算原理图的题目解析都放在最下面 一、2023 年第十四届省赛模拟题1 1.1 Type-C 接口电路 通过 CH340N 将数据转化为…...
聊聊功率器件(氮化镓,碳化硅)
氮化镓和碳化硅是两种具有独特性质和广泛应用的无机物。下面将尽可能详细地解释它们的定义、应用、研究热点以及对我们的价值。 1,氮化镓 氮化镓(GaN)是一种由氮和镓元素组成的化合物,具有直接能隙的半导体特性。其结构类似于纤…...

计算地球圆盘负荷产生的位移
1.研究背景 计算受表面载荷影响的弹性体变形问题有着悠久的历史,涉及到许多著名的数学家和物理学家(Boussinesq 1885;Lamb 1901;Love 1911,1929;Shida 1912;Terazawa 1916;Munk &…...

Harbor介绍
1.什么是Harbor Harbor是一个开源的企业级Docker Registry管理项目,由VMware公司开源。 Harbor提供了比Docker官方公共镜像仓库更为丰富和安全的功能,尤其适合企业环境使用。以下是Harbor的一些关键特性: 权限管理(RBAC&#x…...

解决jenkins运行磁盘满的问题
参考:https://blog.csdn.net/ouyang_peng/article/details/79225993 分配磁盘空间相关操作: https://cloud.tencent.com/developer/article/2230624 登录jenkins相对应的服务或容器中查看磁盘情况: df -h在102挂载服务器上看到是这两个文件…...

使用echart绘制拓扑图,树类型,自定义tooltip和label样式,可收缩
效果如图: 鼠标移上显示 vue3 - ts文件 “echarts”: “^5.4.3”, import { EChartsOption } from echarts import * as echarts from echarts/core import { TooltipComponent } from echarts/components import { TreeChart } from echarts/charts import { C…...

常用的6个的ChatGPT网站,国内可用!
GPTGod 🌐 链接: GPTGod 🏷️ 标签: GPT-4 免费体验 支持API 支持绘图 付费选项 📝 简介:GPTGod 是一个功能全面的平台,提供GPT-4的强大功能,包括API接入和绘图支持。用户可以选择免…...

Linux课程____Samba文件共享服务
一、 Samba服务基础 SMB协议,服务消息块 CIFS协议,通用互联网文件系统 1.Samba 服务器的主要程序 smbd:提供对服务器中文件、打印资源的共享访问 nmbd:提供基于 NetBlOS 主机名称的解析 2.目录文件 /etc/samba/smb.conf 检查工具:test…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...

Opencv中的addweighted函数
一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...
第25节 Node.js 断言测试
Node.js的assert模块主要用于编写程序的单元测试时使用,通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试,通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...

微信小程序云开发平台MySQL的连接方式
注:微信小程序云开发平台指的是腾讯云开发 先给结论:微信小程序云开发平台的MySQL,无法通过获取数据库连接信息的方式进行连接,连接只能通过云开发的SDK连接,具体要参考官方文档: 为什么? 因为…...

Docker 本地安装 mysql 数据库
Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker ;并安装。 基础操作不再赘述。 打开 macOS 终端,开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...

GO协程(Goroutine)问题总结
在使用Go语言来编写代码时,遇到的一些问题总结一下 [参考文档]:https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现: 今天在看到这个教程的时候,在自己的电…...

在 Spring Boot 中使用 JSP
jsp? 好多年没用了。重新整一下 还费了点时间,记录一下。 项目结构: pom: <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://ww…...

Selenium 查找页面元素的方式
Selenium 查找页面元素的方式 Selenium 提供了多种方法来查找网页中的元素,以下是主要的定位方式: 基本定位方式 通过ID定位 driver.find_element(By.ID, "element_id")通过Name定位 driver.find_element(By.NAME, "element_name"…...
深入浅出JavaScript中的ArrayBuffer:二进制数据的“瑞士军刀”
深入浅出JavaScript中的ArrayBuffer:二进制数据的“瑞士军刀” 在JavaScript中,我们经常需要处理文本、数组、对象等数据类型。但当我们需要处理文件上传、图像处理、网络通信等场景时,单纯依赖字符串或数组就显得力不从心了。这时ÿ…...
【系统架构设计师-2025上半年真题】综合知识-参考答案及部分详解(回忆版)
更多内容请见: 备考系统架构设计师-专栏介绍和目录 文章目录 【第1题】【第2题】【第3题】【第4题】【第5题】【第6题】【第7题】【第8题】【第9题】【第10题】【第11题】【第12题】【第13题】【第14题】【第15题】【第16题】【第17题】【第18题】【第19题】【第20~21题】【第…...