MySQL 实验 6:定义数据的完整性

MySQL 实验 6:定义数据的完整性

数据的完整性是指通过某种规则限制数据的取值范围。数据的完整性又称为完整性约束或完整性规则。根据规则的不同,关系数据库的完整性分为三种:实体完整性,参照完整性,用户自定义完整性。

一、实体完整性

实体完整性用来限制关系中主码的取值不能为空,当然主码也不能取重复值。

MySQL 通过定义 primary key 约束定义主码,则 primary key 约束所包含的列不能取空值,也不能取重复值。

MySQL 的 unique 约束可以限制所包含的列不能取重复值,但默认可以取空值,可以通过添加 NOT NULL 选项限制其不能取空值。

1、primary key(主键)约束

根据主码所包含的列数不同,分为两种:单属性码(主码只包含一个属性),多属性码(主码包含多个属性)。一个表只能定义一个主键,定义 primary key 约束的语法如下:

-- 单属性码的定义
create table table_name(
    col_name data_type primary key,
    col_name data_type,
    ... ,
    col_name data_type
);

-- 多属性码的定义(单属性码也可以采用该种格式,单属性码可以看做是特殊的多属性码)
create table table_name(
    col_name data_type,
    col_name data_type,
    ... ,
    col_name data_type,
    primary key(col_name, col_name, ...)
);

举例:

create table stu(
    s_id char(11) primary key,
    s_name char(20),
    gender char(2),
    birth date
);

create table course(
    c_id char(3) primary key,
    c_name char(50)
);

create table score(
    s_id char(11),
    c_id char(3),
    score int,
    primary key(s_id, c_id)
);

上述三张表的表结构如下:

-- PRI 包含的列为主键
mysql> desc stu;   
+--------+----------+------+-----+---------+-------+
| Field  | Type     | Null | Key | Default | Extra |
+--------+----------+------+-----+---------+-------+
| s_id   | char(11) | NO   | PRI | NULL    |       |
| s_name | char(20) | YES  |     | NULL    |       |
| gender | char(2)  | YES  |     | NULL    |       |
| birth  | date     | YES  |     | NULL    |       |
+--------+----------+------+-----+---------+-------+
4 rows in set (0.01 sec)

-- PRI 包含的列为主键
mysql> desc course;
+--------+----------+------+-----+---------+-------+
| Field  | Type     | Null | Key | Default | Extra |
+--------+----------+------+-----+---------+-------+
| c_id   | char(3)  | NO   | PRI | NULL    |       |
| c_name | char(50) | YES  |     | NULL    |       |
+--------+----------+------+-----+---------+-------+
2 rows in set (0.01 sec)

-- PRI 包含的列为主键:该表中有两个 PRI,表示一个主键包含两个属性,而不是两个主键
mysql> desc score;   
+-------+----------+------+-----+---------+-------+
| Field | Type     | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+-------+
| s_id  | char(11) | NO   | PRI |         |       |
| c_id  | char(3)  | NO   | PRI |         |       |
| score | int(11)  | YES  |     | NULL    |       |
+-------+----------+------+-----+---------+-------+
3 rows in set (0.01 sec)
2、unique 约束

unique 约束又称为唯一约束,可以保证 unique 约束所包含的列取值唯一。定义 unique 约束与 primary key 约束格式相近,但一个表可以定义多个 unique 约束。语法如下:

-- 单属性码的定义
create table table_name(
    col_name data_type,
    col_name data_type unique,
    ... ,
    col_name data_type
);

-- 多属性码的定义(单属性码也可以采用该种格式)
create table table_name(
    col_name data_type,
    col_name data_type,
    ... ,
    col_name data_type,
    unique(col_name, col_name, ...)
);

举例:

create table emp(
    e_id int primary key,
    e_name char(30),
    gender char(2),
    salary decimal(10,2),
    phone char(20) unique NOT NULL,  -- 手机号:不能取重复值,并且不能为空
    id_card char(18) unique,         -- 身份证号:不能取重复值,可以为空
    address varchar(200)
);

-- 查看表结构
mysql> desc emp;
+---------+---------------+------+-----+---------+-------+
| Field   | Type          | Null | Key | Default | Extra |
+---------+---------------+------+-----+---------+-------+
| e_id    | int(11)       | NO   | PRI | NULL    |       |
| e_name  | char(30)      | YES  |     | NULL    |       |
| gender  | char(2)       | YES  |     | NULL    |       |
| salary  | decimal(10,2) | YES  |     | NULL    |       |
| phone   | char(20)      | NO   | UNI | NULL    |       |
| id_card | char(18)      | YES  | UNI | NULL    |       |
| address | varchar(200)  | YES  |     | NULL    |       |
+---------+---------------+------+-----+---------+-------+
7 rows in set (0.01 sec)

二、参照完整性

参照完整性:限制外键(foreign key)的取值。

(1)外键可以取空值。

(2)外键如果不取空值,则必须从与之对应的父表的主码中取值。

1、定义 foreign key 约束

MySQL 定义外键的语法如下:

create table table_name(
    col_name data_type,
    col_name data_type,
    ... ,
    col_name data_type,
    foreign key(col_name) references table_name(col_name)
);

举例:新建数据库,在数据库中创建如下四张表

create database stu_db;
use stu_db;

-- 院系表:dept_id 列为主键
create table dept(
    dept_id char(3) primary key,
    dept_name char(50)
);

-- 学生表:s_id 列为主键,dept_id 列为外键,与 dept 表的列 dept_id 对应
create table stu(
    s_id char(11) primary key,
    s_name char(20),
    gender char(2),
    birth date,
    dept_id char(3),
    foreign key(dept_id) references dept(dept_id)
);

-- 可成表:c_id 列为主键
create table course(
    c_id char(3) primary key,
    c_name char(50)
);

-- 成绩表:s_id 与 c_id 两个列为主键
-- s_id 列为外键,与 stu 表的列 s_id 对应
-- c_id 列为外键,与 course 表的列 c_id 对应
create table score(
    s_id char(11),
    c_id char(3),
    score int,
    primary key(s_id, c_id),
    foreign key(s_id) references stu(s_id),
    foreign key(c_id) references course(c_id)
);
2、查看 foreign key 约束

上述四张表的表结构如下:

mysql> desc dept;
+-----------+----------+------+-----+---------+-------+
| Field     | Type     | Null | Key | Default | Extra |
+-----------+----------+------+-----+---------+-------+
| dept_id   | char(3)  | NO   | PRI | NULL    |       |
| dept_name | char(50) | YES  |     | NULL    |       |
+-----------+----------+------+-----+---------+-------+
2 rows in set (0.01 sec)

mysql> desc stu;
+---------+----------+------+-----+---------+-------+
| Field   | Type     | Null | Key | Default | Extra |
+---------+----------+------+-----+---------+-------+
| s_id    | char(11) | NO   | PRI | NULL    |       |
| s_name  | char(20) | YES  |     | NULL    |       |
| gender  | char(2)  | YES  |     | NULL    |       |
| birth   | date     | YES  |     | NULL    |       |
| dept_id | char(3)  | YES  | MUL | NULL    |       |
+---------+----------+------+-----+---------+-------+
5 rows in set (0.01 sec)

mysql> desc course;
+--------+----------+------+-----+---------+-------+
| Field  | Type     | Null | Key | Default | Extra |
+--------+----------+------+-----+---------+-------+
| c_id   | char(3)  | NO   | PRI | NULL    |       |
| c_name | char(50) | YES  |     | NULL    |       |
+--------+----------+------+-----+---------+-------+
2 rows in set (0.01 sec)

mysql> desc score;
+-------+----------+------+-----+---------+-------+
| Field | Type     | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+-------+
| s_id  | char(11) | NO   | PRI |         |       |
| c_id  | char(3)  | NO   | PRI |         |       |
| score | int(11)  | YES  |     | NULL    |       |
+-------+----------+------+-----+---------+-------+
3 rows in set (0.00 sec)

可以使用命令【show create table 表名】查看 foreign key 约束的详情:

mysql> show create table stu\G
*************************** 1. row ***************************
       Table: stu
Create Table: CREATE TABLE `stu` (
  `s_id` char(11) NOT NULL,
  `s_name` char(20) DEFAULT NULL,
  `gender` char(2) DEFAULT NULL,
  `birth` date DEFAULT NULL,
  `dept_id` char(3) DEFAULT NULL,
  PRIMARY KEY (`s_id`),
  KEY `dept_id` (`dept_id`),
  CONSTRAINT `stu_ibfk_1` FOREIGN KEY (`dept_id`) REFERENCES `dept` (`dept_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

mysql> show create table score\G
*************************** 1. row ***************************
       Table: score
Create Table: CREATE TABLE `score` (
  `s_id` char(11) NOT NULL DEFAULT '',
  `c_id` char(3) NOT NULL DEFAULT '',
  `score` int(11) DEFAULT NULL,
  PRIMARY KEY (`s_id`,`c_id`),
  KEY `c_id` (`c_id`),
  CONSTRAINT `score_ibfk_1` FOREIGN KEY (`s_id`) REFERENCES `stu` (`s_id`),
  CONSTRAINT `score_ibfk_2` FOREIGN KEY (`c_id`) REFERENCES `course` (`c_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
3、验证 foreign key 约束的生效情况

说明:

(1)插入数据时, foreign key 约束限制子表中数据的取值。

(2)删除和更新数据时, foreign key 约束也会限制父表中数据的取值。

(3)创建表时,需要先创建父表,才能在子表中创建 foreign key 约束。删除表时,必须先删除子表,才能删除父表。

下面以 dept 与 stu 两张表为例,验证 foreign key 约束的生效情况。

在 dept 表中输入如下的数据:

insert into dept values('D01', '管理系');
insert into dept values('D02', '计算机系');
insert into dept values('D03', '机电系');
insert into dept values('D04', '法律系');

-- 查看数据
mysql> select * from dept;
+---------+-----------+
| dept_id | dept_name |
+---------+-----------+
| D01     | 管理系    |
| D02     | 计算机系  |
| D03     | 机电系    |
| D04     | 法律系    |
+---------+-----------+
4 rows in set (0.00 sec)

在 stu 表中输入如下的数据(正常数据,满足 foreign key 约束):

insert into stu values('20230224101', '李刚', '男', '2005-10-8', 'D01');
insert into stu values('20230224102', '张静静', '女', '2005-6-12', 'D01');
insert into stu values('20230224103', '李梅', '女', '2004-12-18', 'D01');
insert into stu values('20230224201', '王大鹏', '男', '2005-6-30', 'D02');
insert into stu values('20230224202', '张九龄', '男', '2004-11-19', 'D02');

-- 查看数据
mysql> select * from stu;
+-------------+--------+--------+------------+---------+
| s_id        | s_name | gender | birth      | dept_id |
+-------------+--------+--------+------------+---------+
| 20230224101 | 李刚   || 2005-10-08 | D01     |
| 20230224102 | 张静静 || 2005-06-12 | D01     |
| 20230224103 | 李梅   || 2004-12-18 | D01     |
| 20230224201 | 王大鹏 || 2005-06-30 | D02     |
| 20230224202 | 张九龄 || 2004-11-19 | D02     |
+-------------+--------+--------+------------+---------+
5 rows in set (0.00 sec)

在 stu 表中输入如下的数据(报错!违反了 foreign key 约束):

mysql> insert into stu values('20230224601', '李逵', '男', '2005-3-25', 'D06');
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`stu_db`.`stu`, 
上一篇:操作系统笔记


下一篇:Semantic Communication Meets Edge Intelligence——构造终端共享的知识图谱指导无线物联网通信中文本的传输