【postgresql 基础入门】表的约束(一)主键与外键,数据的实体完整性与参照完整性,外键引用数据被修改时的动作触发

主键与外键-表的约束(一)

专栏内容

  • postgresql内核源码分析
  • 手写数据库toadb
  • 并发编程

个人主页:我的主页
管理社区:开源数据库
座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物.

系列文章

  • 入门准备
  • postgrersql基础架构
  • 快速使用
  • 初始化集群
  • 数据库服务管理
  • psql客户端使用
  • pgAdmin图形化客户端
  • 数据库的使用
  • 创建数据库
  • 数据库操作
  • 表的使用
  • 表的创建
  • 表的操作
  • 数据查询
  • 数据查询
  • 多表联合查询
  • 数据操作
  • 插入数据的方式

文章目录

  • 主键与外键-表的约束(一)
  • 系列文章
  • 一、概述
    • 约束的定义
    • 约束的分类
  • 二、主键约束
    • 定义主键约束
    • 修改添加主键约束
    • 删除主键约束
  • 三、外键约束
    • 定义外键约束
    • 修改表添加外键约束
    • 删除外键约束
    • 自引用外键
    • 被引用表的变动影响
      • 数据变动
      • 表删除
  • 四、总结
  • 五、结尾

一、概述


在数据库中,数据类型可以限制数据存储的大小,也能在一定程度上限制存储的数据种类,但是对于数据库应用来讲,它太宽泛了,比如有些表示人名的字段,就不能为空,货物数量的字段,不能为负值,这与实际生活符合,而数据类型并不能做这些约束,这就需要数据库提供一套更贴近应用,或者说与现实世界更符合的规则,来约束数据的有效性。

约束的定义

数据库的约束是一种规则,用于限制或规范数据库中的数据,确保数据的完整性和一致性。这些约束可以定义在表级别或列级别,处理机制是一致的。约束不占用任何数据库空间,而是存在于数据字典中,并在执行SQL期间使用。用户可以指明约束是启用的还是禁用的,当约束启用时,它增强了数据的完整性。

约束的分类

postgresql数据库中的约束类型主要包括以下几种:

  1. 主键约束(Primary Key):主键约束相当于唯一约束和非空约束的组合。它确保表中的每一行数据都有一个唯一标识符,不允许重复,也不允许出现空值。每个表最多只允许一个主键。当创建主键约束时,系统默认会在所在的列或列组合上建立对应的唯一索引。
  2. 外键约束(Foreign Key):外键约束用于保证一个或两个表之间的参照完整性。它构建于一个表的两个字段或是两个表的两个字段之间的参照关系。
  3. 唯一约束(Unique):唯一约束要求指定的表列或列组合的值不能重复,保证数据的唯一性。同一个表可以有多个唯一约束。在创建唯一约束时,如果不给唯一约束名称,就默认和列名相同。与主键约束不同,唯一约束允许空值的存在,但只能出现一个空值。
  4. 非空约束(NOT NULL):非空约束用于确保当前列的值不为空值。它只能出现在表对象的列上。
  5. 检查约束(Check):检查约束会判断指定的条件是否为true,当为true时符合约束。
  6. 排除约束(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同时引用了ordersproducts两张表的列,下面选择将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
如有错误或者疏漏欢迎指出,互相学习。

注:未经同意,不得转载!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/763663.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2核4G服务器阿里云性能测评和优惠价格表

阿里云2核4G服务器租用优惠价格,轻量2核4G服务器165元一年、u1服务器2核4G5M带宽199元一年、云服务器e实例30元3个月,活动链接 aliyunfuwuqi.com/go/aliyun 活动链接如下图: 阿里云2核4G服务器优惠价格 轻量应用服务器2核2G4M带宽、60GB高效…

Debezium日常分享系列之:Debezium2.5稳定版本之数据类型映射

Debezium日常分享系列之:Debezium2.5稳定版本之数据类型映射 一、基本类型二、时间类型三、Decimal类型四、Boolean values布尔值五、Spatial types空间类型六、Debezium技术总结 Debezium MySQL 连接器表示对带有事件的行的更改,这些事件的结构类似于该…

MySQL数据库存储引擎MyISAM与InnoDB

前言 MySQL存储引擎是MySQL数据库中负责管理数据存储和检索的组件,不同的存储引擎提供了不同的功能和特性,可以根据实际需求选择合适的存储引擎来优化数据库性能和功能。以下是一些常见的MySQL存储引擎:InnoDB、MyISAM、MEMORY、NDB Cluster…

【LeetCode】--- 动态规划 集训(一)

目录 一、1137. 第 N 个泰波那契数1.1 题目解析1.2 状态转移方程1.3 解题代码 二、面试题 08.01. 三步问题2.1 题目解析2.2 状态转移方程2.3 解题代码 三、746. 使用最小花费爬楼梯3.1 题目解析3.2 状态转移方程3.3 解题代码 一、1137. 第 N 个泰波那契数 题目地址&#xff1a…

苏州城市学院芮国强一行莅临聚合数据走访调研

3月19日,苏州城市学院校党委书记芮国强、校长赵志宏一行莅临聚合数据,就数据科技赋能行业升级展开调研。聚合数据董事长左磊接待来访。 城市学院党委理论学习中心组一行参观了聚合数据展厅,了解了聚合数据的发展历程、数据产品、应用案例、奖…

QT信号和槽机制connect用法

信号与槽机制是绝对不可或缺且常用的&#xff0c;其中的参数一般都会比较简单&#xff0c;bool、int、QString之类的&#xff0c;但当我们想要传递相对比较复杂的参数&#xff0c;例如QVector<int>、QList<QString>&#xff0c;以及一些我们自定义的结构体时&#…

常用的6个的ChatGPT网站,国内可用!

GPTGod &#x1f310; 链接&#xff1a; GPTGod &#x1f3f7;️ 标签&#xff1a; GPT-4 免费体验 支持API 支持绘图 付费选项 &#x1f4dd; 简介&#xff1a;GPTGod 是一个功能全面的平台&#xff0c;提供GPT-4的强大功能&#xff0c;包括API接入和绘图支持。用户可以选择免…

【WPF应用5】WPF中的TextBlock控件:属性与事件详解及示例

在WPF&#xff08;Windows Presentation Foundation&#xff09;开发中&#xff0c;TextBlock控件是一个常用的元素&#xff0c;用于显示静态或动态文本内容。它提供了丰富的属性和事件&#xff0c;使得开发者能够灵活地控制文本的显示样式和响应用户的交互行为。本文将详细介绍…

数理最适化笔记1

1.1数理最适化是什么&#xff1f; 实际的问题通过数学公式表达出来&#xff0c;并且找到最优解的一种方叫做数理最适化。 数理最适化问题通常是 目的函数&#xff0c;和制约条件组成。 数理最适化问题有很多&#xff0c;最基本的叫做 线性最适化问题 eg. minimize 3x4y s.…

深入BEV感知中的魔鬼细节:综述、评估和秘诀

深入BEV感知中的魔鬼细节&#xff1a;综述、评估和秘诀 论文链接&#xff1a;https://arxiv.org/pdf/2209.05324.pdf 学习感知任务的鸟瞰图&#xff08;BEV&#xff09;中的强大表示法是一种趋势&#xff0c;并引起了工业界和学术界的广泛关注。大多数自动驾驶常规方法是在前…

【那些年错过的好书】——TypeScript+Vue.js前端开发从入门到精通

喜欢前端的同学&#xff0c;可以私信我加入学习群&#xff0c;或关注公众号——【前端系列教程】 正文开始 前言推荐理由作者简介书籍特点章节介绍实书示例写在最后 前言 陌生的朋友&#xff0c;你是否曾为前途而迷茫&#xff0c;看不到努力的价值&#xff0c;时常感到焦虑………

一些常用的Python小技巧

python小技巧 使用列表推导式&#xff1a;列表推导式是一种简洁的方式生成新的列表。例如&#xff0c;可以使用列表推导式快速生成一个递增的数字列表&#xff1a;numbers [x for x in range(10)]。 使用enumerate()函数&#xff1a;enumerate()函数用于在迭代过程中同时获取…

linux系统kubernetes的deployment使用

deployment deployment概念示例文件说明deployment可用字段服务暴露 deployment 概念 deployment 》deploy //可以简写kubectl create deployment myweb --imagenginx --dry-run -o yaml > nginx.yaml 创建文件kubectl expose deployment myweb --nameweb-svc --port8…

MySQL中Buffer pool、Log Buffer和redo、undo日志介绍

MySQL中Buffer pool、Log Buffer和redo、undo日志介绍 Buffer Pool 原理MySQL中的内存结构Buffer PoolChange BufferLog Buffer redo和undo日志redo日志为什么需要REDO日志redo log 基本概念redo的组成redo的整体流程redo log的刷盘策略 undo 日志undo log 基本概念undo log的作…

Qt 不同数据类型转换

一.不同类型数据转换示例&#xff1a; #include <QGuiApplication> #include <QQmlApplicationEngine> #include <QJsonDocument> #include <QJsonObject> #include <QDebug>int main(int argc, char *argv[]) {QCoreApplication::setAttribute…

使用Python的smtplib和email模块实现邮件收发功能

&#x1f4e7; 使用Python的smtplib和email模块实现邮件收发功能 在Python中&#xff0c;smtplib和email模块是处理电子邮件的强大工具。本文将通过多个案例代码&#xff0c;详细介绍如何使用这两个模块来发送和接收电子邮件。&#x1f680; &#x1f528; 环境准备 在开始之…

别踩坑!2024年小红书代写代发机构选择指南!

在小红书平台上&#xff0c;一篇优质的内容往往能迅速吸引用户的关注&#xff0c;为品牌带来不可估量的曝光和转化。然而&#xff0c;对于许多品牌来说&#xff0c;创作高质量的小红书内容并非易事。因此&#xff0c;选择一家专业的小红书代写代发机构成为了不少品牌的明智之选…

【前端Vue】社交信息头条项目完整笔记第2篇:二、登录注册,准备【附代码文档】

社交媒体-信息头条项目完整开发笔记完整教程&#xff08;附代码资料&#xff09;主要内容讲述&#xff1a;一、项目初始化使用 Vue CLI 创建项目,加入 Git 版本管理,调整初始目录结构,导入图标素材,引入 Vant 组件库,移动端 REM 适配,关于 , 配置文件,封装请求模块。十、用户关…

线程池相关详解

1.线程池的核心参数 线程池核心参数主要参考ThreadPoolExecutor这个类的7个参数的构造函数&#xff1a; corePoolSize核心线程数目 maximumPoolSize最大线程数目&#xff08;核心线程救急线程的最大数目&#xff09; keepAliveTime生存时间:救急线程的生存时间&#xff0c;生…

【Linux中vim系列】如何在vim中检索字符串

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…