数据库之 约束条件和级联

2024-01-29 03:12

本文主要是介绍数据库之 约束条件和级联,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

【一】什么是约束条件

  • 在数据库中,约束条件是一组规则条件,用于限制表中数据的值,以确保数据的完整性一致性

  • 约束条件可以应用于表的列级别表级别,它们定义了数据库中数据的有效性和规范性。

  • 约束条件在创建表时可以使用, 也可以修改表的时候添加约束条件。

  • 凡是不符合约束的数据,插入时就会失败

【二】非空约束

  • NOT NULL

【1】作用

  • 限制字段不能为NULL

【2】示例

  • 创建表
mysql> create table t1(-> name varchar(6) not null,	--名字不能为空-> another_name varchar(6)	--别名可以为空-> );
  • 插入,并查看
mysql> insert t1 values('bruce', null);
Query OK, 1 row affected (0.01 sec)mysql> select * from t1;
+-------+--------------+
| name  | another_name |
+-------+--------------+
| bruce | NULL         |
+-------+--------------+
1 row in set (0.00 sec)

【三】唯一性约束

  • UNIQUE

【1】作用

  • 唯一约束确保列或一组列中的所有值都是唯一的,但允许包含空值。
    • 空值可以有多个
    • 具体值唯一

【2】示例

  • 修改表
mysql> alter table t1 add id int unique;	--添加唯一性约束id
Query OK, 0 rows affected (0.07 sec)
  • 插入,并查看
mysql> insert t1 (id, name) values (null, 'kan'), (1, 'lanny');	--插入一个空值和一个1
Query OK, 2 rows affected (0.00 sec)mysql> select id, name, another_name from t1;	--发现空值确实可以有多个
+------+-------+--------------+
| id   | name  | another_name |
+------+-------+--------------+
| NULL | bruce | NULL         |
| NULL | kan   | NULL         |
|    1 | lanny | NULL         |
+------+-------+--------------+

【四】组合使用

  • NOT NULL && UNIQUE

【1】作用

  • 同时满足多个约束,不能为空且唯一

【2】示例

  • 将name添加唯一性约束
mysql> alter table t1 modify name varchar(6) not null unique;
Query OK, 0 rows affected (0.08 sec)
  • 查看表结构
mysql> desc t1;
+--------------+------------+------+-----+---------+-------+
| Field        | Type       | Null | Key | Default | Extra |
+--------------+------------+------+-----+---------+-------+
| name         | varchar(6) | NO   | PRI | NULL    |       |
| another_name | varchar(6) | YES  |     | NULL    |       |
| id           | int(11)    | YES  | UNI | NULL    |       |
+--------------+------------+------+-----+---------+-------+

【五】查看约束条件

【1】表级约束

  • TABLE_CONSTRAINTS 表是 information_schema 数据库中的一张表,它存储了有关表级约束(例如主键、唯一键、外键等)的信息。
show databases;	--查看所有数据库
use information_schema;	--切换数据库
show tables;	--查看所有表
desc table_constraints;	--查看表的结构
mysql> desc table_constraints;
+--------------------+--------------+------+-----+---------+-------+
| Field              | Type         | Null | Key | Default | Extra |
+--------------------+--------------+------+-----+---------+-------+
| CONSTRAINT_CATALOG | varchar(512) | NO   |     |         |       |
| CONSTRAINT_SCHEMA  | varchar(64)  | NO   |     |         |       |
| CONSTRAINT_NAME    | varchar(64)  | NO   |     |         |       |
| TABLE_SCHEMA       | varchar(64)  | NO   |     |         |       |
| TABLE_NAME         | varchar(64)  | NO   |     |         |       |
| CONSTRAINT_TYPE    | varchar(64)  | NO   |     |         |       |
+--------------------+--------------+------+-----+---------+-------+

【2】参数说明

  • CONSTRAINT_CATALOG: 约束所属的目录名称。
  • CONSTRAINT_SCHEMA: 约束所属的数据库名称。
  • CONSTRAINT_NAME: 约束的名称。
  • TABLE_SCHEMA: 表所属的数据库名称。
  • TABLE_NAME: 表的名称。
  • CONSTRAINT_TYPE: 约束的类型,可能是 'PRIMARY KEY''UNIQUE''FOREIGN KEY' 等。

【3】查看指定表的表级约束

  • 语法
SELECT CONSTRAINT_NAME, CONSTRAINT_TYPE
FROM information_schema.TABLE_CONSTRAINTS
WHERE TABLE_NAME = '表名';

【五】表级约束和列级约束

【1】定义位置不同

  • 表级约束:在表的定义末尾声明的,通常包含对表中多个列的约束条件

  • 列级约束:在定义每个列的时候声明的,它与特定列相关

【2】适用范围

  • 表级约束:表级约束提供更大的灵活性和复杂性,适用于需要涉及多列可以跨表的约束条件。

  • 列级约束:在定义每个列的时候声明的,它与特定列相关。

【3】示例

  • 创建新表
    • name1和hobby1都是用的列级别约束
    • name2和hobby2用的是表级约束
mysql> create table t2(-> name1 varchar(6) not null,-> hobby1 varchar(10) not null,-> name2 varchar(6),-> hobby2 varchar(10),-> constraint my_not_null check(name2 is not null and hobby2 is not null)-> );
  • 插入数据
mysql> insert t2 values('burce','lily','kan',null);
Query OK, 1 row affected (0.01 sec)mysql> insert t2 values(null, 'cici', null, 'lulu');
ERROR 1048 (23000): Column 'name1' cannot be nullmysql> insert t3 values('lily', 'eat', null, null);
Query OK, 1 row affected (0.01 sec)
  • 在你的表定义中,你创建了一个名为 my_not_null 的约束,该约束使用 CHECK 关键字来确保 name2hobby2 的值都不为空。然而,MySQL 在处理 CHECK 约束时,并不会强制检查这些条件。

  • 查看试试

mysql> SELECT CONSTRAINT_NAME, CONSTRAINT_TYPE-> FROM information_schema.TABLE_CONSTRAINTS-> WHERE TABLE_NAME = 't2';
Empty set (0.01 sec)

【六】主键约束

【1】说明

  1. 主键约束(Primary Key Constraint): 主键约束是一种数据库约束,它确保表中的特定列(或列的组合)包含唯一且非空的值。主键约束是通过定义主键来实现的,表中只能有一个主键约束
  2. 主键字段(Primary Key Field): 主键字段是被定义为主键的表中的特定列。这个字段的在整个表中必须是唯一的且不能为空
  3. 主键值(Primary Key Value): 主键值是主键字段中的具体数据值。每一行数据都必须有一个唯一的主键值,它用来标识该行数据。

【2】作用

  1. 唯一性和非空性: 主键确保了主键字段的值在整个表中是唯一的,且不能为空。每一行数据都必须具有唯一的主键值。
  2. 索引效果: 定义主键约束的字段会自动创建索引(index),提高数据检索的效率。这使得按主键进行检索或连接操作更为快速。
  3. 数据完整性: 主键确保了表中的每一行都有一个唯一标识,这有助于维护数据的完整性。通过主键,可以避免表中出现重复或空值的情况。
  4. 表的有效性: 一张合理设计的表应该有主键。如果表没有主键,可能导致数据关联和查询的困难,因此主键可以被视为表的有效性标志。

【3】根据个数进行分类

  • 不论时单一主键还是复合主键,一张表只能有一个主键约束。
(1)单一主键约束
  • 给一个字段添加一个主键约束,被称为单一主键
mysql> create table t1(	--列级约束-> id int primary key,-> name varchar(6)-> );
Query OK, 0 rows affected (0.03 sec)mysql> create table t2(	--表级约束-> id int,-> name varchar(6),-> primary key(id)-> );
Query OK, 0 rows affected (0.02 sec)mysql> create table t3(	--给主键重命名-> id int,-> name varchar(6),-> constraint my_id primary key(id)-> );
Query OK, 0 rows affected (0.03 sec)
(2)复合主键
  • 给多个字段联合添加一个主键约束,被称为复合主键
mysql> create table t4(	--复合主键-> id int,-> name varchar(6),-> constraint my_id primary key(id, name)-> );
Query OK, 0 rows affected (0.03 sec)

【4】根据性质分类

(1)自然主键:
  • 特点: 自然主键的值通常是一个自然数,且与业务无直接关系。这种主键是数据库中的一个自然属性,不是为了满足业务需求而人为设计的。
  • 例子: 表中的自增长整数列、日期时间戳等都可以作为自然主键的候选。
(2)业务主键:
  • 特点: 业务主键的值与当前表中的业务紧密相关,通常是为了满足业务需求而人为设计的。业务主键可能是某个实际业务中的标识符,如订单号、产品代码等。
  • 影响: 如果业务发生改变,业务主键可能会受到影响,因此在设计数据库时,使用业务主键要谨慎,避免对数据库的可维护性产生负面影响。
  • 例子: 订单表中的订单号、产品表中的产品代码等都可以作为业务主键的候选。

【5】自增主键

(1)说明
  • 在 MySQL 中,可以通过使用 auto_increment 属性来创建自增主键列。

  • MySQL数据库管理系统中提供了一个自增数字,专门用来自动生成主键值,主键值不需要用户去维护,也不需要用户生成,MySQL会自动生成。

(2)示例
  • 创建表
mysql> create table user_info(-> id int primary key auto_increment,-> name varchar(6)-> ) auto_increment=1;	--默认值为1,可以不写
Query OK, 0 rows affected (0.02 sec)
  • 插入数据
mysql> insert user_info (name) values('bruce'), ('tom');
Query OK, 2 rows affected (0.00 sec)
  • 查看结果
mysql> select * from user_info;
+----+-------+
| id | name  |
+----+-------+
|  1 | bruce |
|  2 | tom   |
+----+-------+

【6】重置主键

(1)为什么要
  • 在删除一行记录的时候,主键还会自增,导致主键值跳跃
  • 在清空数据表的时候,主键值仍将自增,但是主键会自动重置,因为是重构的表
(2)示例
  • 删除数据
mysql> truncate user_info;	--清空
Query OK, 0 rows affected (0.02 sec)
  • 插入一个查看
mysql> insert user_info (name) values('lily');
Query OK, 1 row affected (0.01 sec)mysql> select *from user_info;		--确实会自动重置
+----+------+
| id | name |
+----+------+
|  1 | lily |
+----+------+
1 row in set (0.00 sec)
  • 删除一个再添加
mysql> delete from user_info where id=1;	--删除记录
Query OK, 1 row affected (0.00 sec)mysql> insert user_info (name) values('kan');	-- 插入新纪录
Query OK, 1 row affected (0.01 sec)mysql> select *from user_info;		--主键仍沿着之前的值增加
+----+------+
| id | name |
+----+------+
|  2 | kan  |
+----+------+
1 row in set (0.00 sec)
  • 删除记录,重置主键
mysql> delete from user_info where id=2;	--删除记录
Query OK, 1 row affected (0.01 sec)mysql> alter table user_info auto_increment=1;	--重置主键
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0mysql> insert user_info (name) values('lulu');	--插入新记录
Query OK, 1 row affected (0.01 sec)mysql> select *from user_info;	--查看
+----+------+
| id | name |
+----+------+
|  1 | lulu |
+----+------+
1 row in set (0.00 sec)

【七】外键约束

  • 外键会消耗额外的资源并且会增加表的复杂度
  • 多数通过SQL语句的形式建立逻辑意义上的表关系

【1】说明

  • 外键约束: 用于确保表中某个字段的值与另一表中的字段值相匹配,建立了表与表之间的关系
  • 外键字段: 被定义为外键的表中的特定列,存储与另一表中关联字段相匹配的值。
  • 外键值: 外键字段中的具体数据值,对应着另一表中的关联字段值,建立了数据之间的关联关系。

【2】语法

foreign key(在当前表的字段名) references 关联的表名(关联的表中需要建立外键关系的字段名)

【3】分类和创建示例

(1)一对一关系
1.介绍
  • 在一对一关系中,通常会将数据划分到两个表中,以优化数据库的性能和降低冗余。
    • 用户表: 存储使用频率较高的数据字段,如 QQ 号码、座右铭、个人简介、爱好等。
    • 用户详情表: 存储使用频率较低的数据字段,如邮箱、电话、学校等。
    • 这样的设计可以节省资源,并降低数据库的压力,使得常用数据更容易访问。
  • 外键字段建在任意一方都可以,但是推荐建在查询频率较高的较好的一方
2.示例
  • 创建表
mysql> create table user_info(-> id int primary key auto_increment,-> phone int(11),-> sex char,-> age int-> );
Query OK, 0 rows affected (0.03 sec)mysql> create table user(-> id int primary key auto_increment,-> name varchar(6),-> detail_id int,-> foreign key(detail_id) references user_info(id)-> );
Query OK, 0 rows affected (0.03 sec)
(2)一对多关系
1.介绍
  • 一对多关系是数据库中的一种关联关系,表示一个记录在一个表中可以对应多个记录,在另一个表中同样只对应一个记录。这是数据库中最常见的关联关系之一。
  • 假设有部门和员工两个实体,一个部门可以有多个员工,但一个员工只属于一个部门。这就是一个典型的一对多关系。
    • 部门表: 包含部门的基本信息,例如部门ID(主键)、部门名称等。
    • 员工表: 包含员工的基本信息,例如员工ID(主键)、姓名、部门ID(外键)等。
  • 一对多关系通过在多的一方中添加一个外键
2.示例
  • 创建表
mysql> create table department(-> id int primary key auto_increment,-> name varchar(10)-> );
Query OK, 0 rows affected (0.03 sec)mysql> create table employee(-> id int primary key auto_increment,-> name varchar(6),-> department_id int,-> foreign key(department_id) references department(id)-> );
Query OK, 0 rows affected (0.03 sec)
(3)多对多关系
1.介绍
  • 多对多关系是数据库中的一种关联关系,表示两个表之间存在多对多的对应关系。在这种关系中,一个记录在一个表中可以对应多个记录,在另一个表中同样可以对应多个记录。
  • 典型的多对多关系需要通过**中间表(连接表)**来实现,这个中间表包含两个表的主键作为外键,用于建立两者之间的关联。
    • 学生表: 包含学生的基本信息,例如学生ID(主键)、姓名等。
    • 课程表: 包含课程的基本信息,例如课程ID(主键)、课程名称等。
    • 选课表(中间表): 包含学生ID和课程ID作为外键,用于记录学生选修的课程关系。
2.示例
  • 创建表
mysql> create table student(-> id int primary key auto_increment,-> name varchar(6)-> );
Query OK, 0 rows affected (0.03 sec)mysql> create table course(-> id int primary key auto_increment,-> name varchar(10)-> );
Query OK, 0 rows affected (0.03 sec)mysql> create table student_course(-> stu_id int,-> c_id int,-> id int primary key auto_increment,-> foreign key (stu_id) references student(id),-> foreign key (c_id) references course(id)-> );
Query OK, 0 rows affected (0.07 sec)

【4】插入数据

(1)说明
  • 先向没有外键的表插入数据
  • 再向含有外键的表插入数据
    • 外键不存在会报错
(2)示例
  • 使用一对多的案例
  • 创建部门信息
mysql> insert department (name) values("销售部"), ("开发部"), ("主管部");	--此时部门id有3个
Query OK, 3 rows affected (0.01 sec)
Records: 3  Duplicates: 0  Warnings: 0mysql> select * from department;
+----+-----------+
| id | name      |
+----+-----------+
|  1 | 销售部    |
|  2 | 开发部    |
|  3 | 主管部    |
+----+-----------+
  • 创建员工信息
mysql> insert employee (name, department_id) values('bruce', 4);	--插入没有的外键信息4,报错
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`db2`.`employee`, CONSTRAINT `employee_ibfk_1` FOREIGN KEY (`department_id`) REFERENCES `department` (`id`))
mysql> insert employee (name, department_id) values ('bruce', 3), ('lily', 1), ('kan', 1);	--正常插入数据
Query OK, 3 rows affected (0.01 sec)mysql> select * from employee;
+----+-------+---------------+
| id | name  | department_id |
+----+-------+---------------+
|  2 | bruce |             3 |
|  3 | lily  |             1 |
|  4 | kan   |             1 |
+----+-------+---------------+

【八】级联更新和级联删除

【1】说明

  • 在数据库中,级联更新(Cascade Update)和级联删除(Cascade Delete)是一种设置在外键约束上的操作。它们的作用是在父表的数据发生变化时,自动更新或删除相关联的子表中的数据
  • 添加级联更新和级联删除时,需要在外键约束后面添加相应的操作指令。
  • 删除父表中的数据时,使用 ON DELETE CASCADE 指令,表示级联删除,即同时删除关联的子表中的数据。
  • 更新父表中的数据时,使用 ON UPDATE CASCADE 指令,表示级联更新,即同时更新关联的子表中的数据。

【2】使用

(1)说明
  • 删除外键约束的语法:
ALTER TABLE table_name DROP FOREIGN KEY constraint_name;
  • 添加级联删除的外键约束的语法:
ALTER TABLE child_table ADD CONSTRAINT constraint_name FOREIGN KEY (foreign_key_column) REFERENCES parent_table(primary_key_column) ON DELETE CASCADE;
  • 添加级联更新的外键约束的语法:
ALTER TABLE child_table ADD CONSTRAINT constraint_name FOREIGN KEY (foreign_key_column) REFERENCES parent_table(primary_key_column) ON UPDATE CASCADE;
(2)示例
  • 还是使用一对多的案例
  • 删除员工表外键
    • 由于没有命名外键,需要先查询命名
mysql> show create table employee \G;	--查询外键名字
*************************** 1. row ***************************Table: employee
Create Table: CREATE TABLE `employee` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(6) DEFAULT NULL,`department_id` int(11) DEFAULT NULL,PRIMARY KEY (`id`),KEY `department_id` (`department_id`),CONSTRAINT `employee_ibfk_1` FOREIGN KEY (`department_id`) REFERENCES `department` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4
1 row in set (0.00 sec)ERROR:
No query specifiedmysql> alter table employee drop foreign key employee_ibfk_1;	--删除外键
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0
  • 添加级联删除和更新外键
mysql> alter table employee add constraint employee_ibfk_1 foreign key (department_id) references department(id) on update cascade on delete cascade;
Query OK, 3 rows affected (0.06 sec)
  • 修改部门id,查看员工表对应id是否修改
    • 可以
mysql> update department-> set id=5-> where id=1;
Query OK, 1 row affected (0.02 sec)	
Rows matched: 1  Changed: 1  Warnings: 0mysql> select * from employee;
+----+-------+---------------+
| id | name  | department_id |
+----+-------+---------------+
|  2 | bruce |             3 |
|  3 | lily  |             5 |
|  4 | kan   |             5 |
+----+-------+---------------+
  • 删除部门id,查看员工表对应id员工是否删除
    • 可以
mysql> delete from department-> where id=3;
Query OK, 1 row affected (0.01 sec)mysql> select *from employee;
+----+------+---------------+
| id | name | department_id |
+----+------+---------------+
|  3 | lily |             5 |
|  4 | kan  |             5 |
+----+------+---------------+
  • 员工表是否可以添加未知部门id
    • 不行
mysql> insert employee (name, department_id) values('lulu', 0);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`db2`.`employee`, CONSTRAINT `employee_ibfk_1` FOREIGN KEY (`department_id`) REFERENCES `department` (`id`) ON DELETE CASCADE ON UPDATE CASCADE)

【3】谨慎使用:

  • 级联操作会直接影响相关联的表中的数据,因此在使用时需要谨慎。数据的完整性和一致性是数据库设计的重要考虑因素,因此在设置级联操作时需要明确了解其影响。
  • 在修改约束条件时,建议删除原先的约束再重新添加新的约束条件,以确保操作的准确性。

这篇关于数据库之 约束条件和级联的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/655572

相关文章

数据库oracle用户密码过期查询及解决方案

《数据库oracle用户密码过期查询及解决方案》:本文主要介绍如何处理ORACLE数据库用户密码过期和修改密码期限的问题,包括创建用户、赋予权限、修改密码、解锁用户和设置密码期限,文中通过代码介绍... 目录前言一、创建用户、赋予权限、修改密码、解锁用户和设置期限二、查询用户密码期限和过期后的修改1.查询用

mysql数据库分区的使用

《mysql数据库分区的使用》MySQL分区技术通过将大表分割成多个较小片段,提高查询性能、管理效率和数据存储效率,本文就来介绍一下mysql数据库分区的使用,感兴趣的可以了解一下... 目录【一】分区的基本概念【1】物理存储与逻辑分割【2】查询性能提升【3】数据管理与维护【4】扩展性与并行处理【二】分区的

IDEA如何切换数据库版本mysql5或mysql8

《IDEA如何切换数据库版本mysql5或mysql8》本文介绍了如何将IntelliJIDEA从MySQL5切换到MySQL8的详细步骤,包括下载MySQL8、安装、配置、停止旧服务、启动新服务以及... 目录问题描述解决方案第一步第二步第三步第四步第五步总结问题描述最近想开发一个新应用,想使用mysq

Oracle数据库使用 listagg去重删除重复数据的方法汇总

《Oracle数据库使用listagg去重删除重复数据的方法汇总》文章介绍了在Oracle数据库中使用LISTAGG和XMLAGG函数进行字符串聚合并去重的方法,包括去重聚合、使用XML解析和CLO... 目录案例表第一种:使用wm_concat() + distinct去重聚合第二种:使用listagg,

Java读取InfluxDB数据库的方法详解

《Java读取InfluxDB数据库的方法详解》本文介绍基于Java语言,读取InfluxDB数据库的方法,包括读取InfluxDB的所有数据库,以及指定数据库中的measurement、field、... 首先,创建一个Java项目,用于撰写代码。接下来,配置所需要的依赖;这里我们就选择可用于与Infl

详谈redis跟数据库的数据同步问题

《详谈redis跟数据库的数据同步问题》文章讨论了在Redis和数据库数据一致性问题上的解决方案,主要比较了先更新Redis缓存再更新数据库和先更新数据库再更新Redis缓存两种方案,文章指出,删除R... 目录一、Redis 数据库数据一致性的解决方案1.1、更新Redis缓存、删除Redis缓存的区别二

oracle数据库索引失效的问题及解决

《oracle数据库索引失效的问题及解决》本文总结了在Oracle数据库中索引失效的一些常见场景,包括使用isnull、isnotnull、!=、、、函数处理、like前置%查询以及范围索引和等值索引... 目录oracle数据库索引失效问题场景环境索引失效情况及验证结论一结论二结论三结论四结论五总结ora

C#实现文件读写到SQLite数据库

《C#实现文件读写到SQLite数据库》这篇文章主要为大家详细介绍了使用C#将文件读写到SQLite数据库的几种方法,文中的示例代码讲解详细,感兴趣的小伙伴可以参考一下... 目录1. 使用 BLOB 存储文件2. 存储文件路径3. 分块存储文件《文件读写到SQLite数据库China编程的方法》博客中,介绍了文

Android数据库Room的实际使用过程总结

《Android数据库Room的实际使用过程总结》这篇文章主要给大家介绍了关于Android数据库Room的实际使用过程,详细介绍了如何创建实体类、数据访问对象(DAO)和数据库抽象类,需要的朋友可以... 目录前言一、Room的基本使用1.项目配置2.创建实体类(Entity)3.创建数据访问对象(DAO

SQL Server数据库磁盘满了的解决办法

《SQLServer数据库磁盘满了的解决办法》系统再正常运行,我还在操作中,突然发现接口报错,后续所有接口都报错了,一查日志发现说是数据库磁盘满了,所以本文记录了SQLServer数据库磁盘满了的解... 目录问题解决方法删除数据库日志设置数据库日志大小问题今http://www.chinasem.cn天发