RDBMS的数据完整性
本章学习目标
熟练掌握实体完整性
熟练掌握索引
熟练掌握域完整性
熟练掌握引用完整性
理解数据库事务
前面章节学习了数据库与数据表的基本操作,在实际开发中,数据表中的数据是非得多的,数据的准确性与否至关重要。MySQL提供了数据的完整性约束,主要包括实体完整性、域完整性和引用完整性,本章将重点讲解数据的完整性。
5.1 实体完整性
实体完整性是对关系中的记录进行约束,也就是对行的约束。这里主要讲解主键约束、唯一约束和自动增长列。
5.1.1 主键约束
主键(PRIMARY KEY)用于唯一地标识表中的某一条记录。在两个表的关系中,主键用来在一个表中引用来自于另一个表中的特定记录。一个表的主键可以由多个关键字共同组成,并且主键的列不能包含空值。一般用主键定义表中所有行能唯一标识,这就像所有人都有身份证,每个人的身份证号是不同的,能唯一标识每一个人。
接下来通过一个案例演示没有主键会出现哪些问题。首先,这里需要一张订单表orders,表结构如表5.1所示。
表5.1 orders表
字段 |
字段类型 |
说明 |
oid |
INT |
订单号 |
total |
DOUBLE |
订单金额总计 |
name |
VARCHAR(20) |
收货人 |
phone |
VARCHAR(20) |
收货人电话 |
addr |
VARCHAR(50) |
收货人地址 |
表5.1中列出了订单表的字段、字段类型和说明,接着创建订单表,SQL语句如下所示。
mysql> CREATE TABLE orders(
-> oid INT,
-> total DOUBLE,
-> name VARCHAR(20),
-> phone VARCHAR(20),
-> addr VARCHAR(50)
-> );
Query OK, 0 rows affected (0.18 sec)
向订单表中插入一条数据,SQL语句如下所示。
mysql> INSERT INTO orders(
-> oid,
-> total,
-> name,
-> phone,
-> addr
-> )VALUES(
-> 1,
-> 100,
-> 'zs',
-> 1366,
-> 'xxx'
-> );
Query OK, 1 row affected (0.07 sec)
以上执行结果证明插入数据完成,为了进一步验证,可以使用SELECT语句查看orders表中的数据,SQL语句如下所示。
mysql> SELECT * FROM orders;
+------+-------+------+-------+------+
| oid | total | name | phone | addr |
+------+-------+------+-------+------+
| 1 | 100 | zs | 1366 | xxx |
+------+-------+------+-------+------+
1 row in set (0.02 sec)
从以上执行结果可看出,orders表中的数据成功插入,此时再次向表中插入数据,新插入数据的oid仍然为1,SQL语句如下所示。
mysql> INSERT INTO orders(
-> oid,
-> total,
-> name,
-> phone,
-> addr
-> )VALUES(
-> 1,
-> 200,
-> 'ls',
-> 1369,
-> 'yyy'
-> );
Query OK, 1 row affected (0.04 sec)
以上执行结果证明插入数据完成,为了进一步验证,可以使用SELECT语句查看orders表中的数据,SQL语句如下所示。
mysql> SELECT * FROM orders;
+------+-------+------+-------+------+
| oid | total | name | phone | addr |
+------+-------+------+-------+------+
| 1 | 100 | zs | 1366 | xxx |
| 1 | 200 | ls | 1369 | yyy |
+------+-------+------+-------+------+
2 rows in set (0.00 sec)
从以上执行结果可看出,orders表中的数据成功插入,表中此时有两条订单数据,且两个订单的oid都为1,这样的数据明显存在问题,订单号如果相同,商品的付款送货等流程都可能出现问题,为了避免这样的问题,可以为表添加主键约束,为已经存在的表设置主键的语法格式如下所示。
ALTER TABLE 表名
ADD PRIMARY KEY(列名);
以上语法格式中,表名是要修改的已存在的表, PRIMARY KEY代表主键,列名是要设置为主键的列,接下来为orders表添加主键约束,设置oid列为主键,SQL语句如下所示。
mysql> ALTER TABLE orders
-> ADD PRIMARY KEY(oid);
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'
从以上执行结果可看出,添加主键失败,这里报了一个错误,错误的原因是表中已经存在两条oid相同的数据,所以不可添加主键,此时可以使用DELETE语句删除其中一条数据,SQL语句如下所示。
mysql> DELETE FROM orders
-> WHERE name='ls';
Query OK, 1 row affected (0.09 sec)
以上执行结果证明删除数据完成,为了进一步验证,可以使用SELECT语句查看orders表中的数据,SQL语句如下所示。
mysql> SELECT * FROM orders;
+------+-------+------+-------+------+
| oid | total | name | phone | addr |
+------+-------+------+-------+------+
| 1 | 100 | zs | 1366 | xxx |
+------+-------+------+-------+------+
1 rows in set (0.00 sec)
从以上执行结果可看出,表中只有一条数据,不存在oid重复的数据,此时继续设置主键,SQL语句如下所示。
mysql> ALTER TABLE orders
-> ADD PRIMARY KEY(oid);
Query OK, 1 row affected (0.26 sec)
Records: 1 Duplicates: 0 Warnings: 0
以上执行结果证明主键添加完成,为了进一步验证,可以使用DESC查看表结构,SQL语句如下所示。
mysql> DESC orders;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| oid | int(11) | NO | PRI | 0 | |
| total | double | YES | | NULL | |
| name | varchar(20) | YES | | NULL | |
| phone | varchar(20) | YES | | NULL | |
| addr | varchar(50) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
5 rows in set (0.01 sec)
从以上执行结果可看出,字段oid的Key值为“PRI”,代表主键,这时将前面删除的第二条数据再次添加进去,SQL语句如下所示。
mysql> INSERT INTO orders(
-> oid,
-> total,
-> name,
-> phone,
-> addr
-> )VALUES(
-> 1,
-> 200,
-> 'ls',
-> 1369,
-> 'yyy'
-> );
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'
从以上执行结果可看出,插入数据失败,从报错信息可以看出这是因为主键对其进行了约束,新插入的数据主键不能重复,将oid的值改为2,再次插入,SQL语句如下所示。
mysql> INSERT INTO orders(
-> oid,
-> total,
-> name,
-> phone,
-> addr
-> )VALUES(
-> 2,
-> 200,
-> 'ls',
-> 1369,
-> 'yyy'
-> );
Query OK, 1 row affected (0.03 sec)
以上执行结果证明插入数据完成,为了进一步验证,可以使用SELECT语句查看orders表中的数据,SQL语句如下所示。
mysql> SELECT * FROM orders;
+-----+-------+------+-------+------+
| oid | total | name | phone | addr |
+-----+-------+------+-------+------+
| 1 | 100 | zs | 1366 | xxx |
| 2 | 200 | ls | 1369 | yyy |
+-----+-------+------+-------+------+
2 rows in set (0.00 sec)
从以上执行结果可看出,当oid的值不重复时插入成功,另外主键的值不能为NULL,这里继续验证,向表中插入一条数据,oid设置为NULL,SQL语句如下所示。
mysql> INSERT INTO orders(
-> oid,
-> total,
-> name,
-> phone,
-> addr
-> )VALUES(
-> NULL,
-> 300,
-> 'w5',
-> 1591,
-> 'zzz'
-> );
ERROR 1048 (23000): Column 'oid' cannot be null
以上执行结果证明主键的值不能为NULL,当主键插入NULL值时会报错,以上是为已经存在的表添加主键约束,实际上,在创建表时同样可以添加主键约束,具体语法格式如下所示。
CREATE TABLE 表名(
字段名 数据类型 PRIMARY KEY
);
以上语法格式中,字段名是要设置为主键的列名,数据类型为该列的数据类型,PRIMARY KEY代表主键,接下来通过一个案例演示建表时添加主键约束。
例5-1 创建订单表orders2,表结构与前面的orders表相同,在创建表的同时,为oid列添加主键约束,SQL语句如下所示。
mysql> CREATE TABLE orders2(
-> oid INT PRIMARY KEY,
-> total DOUBLE,
-> name VARCHAR(20),
-> phone VARCHAR(20),
-> addr VARCHAR(50)
-> );
Query OK, 0 rows affected (0.08 sec)
以上执行结果证明表orders2创建完成并添加主键,为了进一步验证,可以使用DESC查看表结构,SQL语句如下所示。
mysql> DESC orders2;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| oid | int(11) | NO | PRI | NULL | |
| total | double | YES | | NULL | |
| name | varchar(20) | YES | | NULL | |
| phone | varchar(20) | YES | | NULL | |
| addr | varchar(50) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
5 rows in set (0.02 sec)
从以上执行结果可看出,字段oid的Key值为“PRI”,说明主键约束添加成功。
前面的案例中讲解了添加单字段的主键约束,但随着业务的复杂,可能会需要多字段的主键约束,例如手机接收信息,这时通过手机号就不能够唯一确定一条记录,可能一个手机号在一天中接收了很多的信息,解决这个问题可以添加主键约束为手机号和时间戳两个列,根据两个列的数据,能够唯一确定一条记录,添加多字段的主键约束语法格式如下所示。
CREATE TABLE 表名(
字段名1 数据类型,
字段名2 数据类型,
……
PRIMARY KEY(字段名1,字段名2,字段名n)
);
以上语法格式中,PRIMARY KEY中的参数代表构成主键的多个字段的名称,接下来通过一个案例演示添加多字段的主键约束。
例5-2 创建订单表orders3,表结构与前面的orders表相比,多了一个INT类型的pid字段,该字段代表商品id,在创建表的同时,为oid和pid两列添加主键约束,SQL语句如下所示。
mysql> CREATE TABLE orders3(
-> oid INT,
-> pid INT,
-> total DOUBLE,
-> name VARCHAR(20),
-> phone VARCHAR(20),
-> addr VARCHAR(50),
-> PRIMARY KEY(oid,pid)
-> );
Query OK, 0 rows affected (0.07 sec)
以上执行结果证明表orders3创建完成并添加主键,为了进一步验证,可以使用DESC查看表结构,SQL语句如下所示。
mysql> DESC orders3;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| oid | int(11) | NO | PRI | 0 | |
| pid | int(11) | NO | PRI | 0 | |
| total | double | YES | | NULL | |
| name | varchar(20) | YES | | NULL | |
| phone | varchar(20) | YES | | NULL | |
| addr | varchar(50) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
6 rows in set (0.01 sec)
从以上执行结果可看出,字段oid和字段pid的Key值都为“PRI”,说明多个字段的主键约束添加成功。
5.1.2 唯一约束
唯一约束用于保证数据表中字段值的唯一性,MySQL中使用UNIQUE关键字添加唯一约束,在创建表时,可以为某个字段添加唯一约束,具体语法格式如下所示。
CREATE TABLE 表名(
字段名 数据类型 UNIQUE,
……
);
以上语法格式中,字段名是要添加唯一约束的列名,列名后跟着数据类型和UNIQUE关键字,之间用空格隔开,接下来通过一个案例演示唯一约束的用法。
例5-3 创建员工表emp,并按表结构添加约束,表结构如表5.2所示。
表5.2 emp表
字段 |
字段类型 |
约束 |
说明 |
id |
INT |
PRIMARY KEY |
员工编号 |
name |
VARCHAR(20) |
|
员工姓名 |
phone |
VARCHAR(20) |
UNIQUE |
员工电话 |
addr |
VARCHAR(50) |
|
员工住址 |
表5.2中列出了emp表的结构,包含四个字段,其中id字段需要添加主键约束,phone字段需要添加唯一约束,SQL语句如下所示。
mysql> CREATE TABLE emp(
-> id INT PRIMARY KEY,
-> name VARCHAR(20),
-> phone VARCHAR(20) UNIQUE,
-> addr VARCHAR(50)
-> );
Query OK, 0 rows affected (0.08 sec)
以上执行结果证明表emp创建完成并添加约束,为了进一步验证,可以使用DESC查看表结构,SQL语句如下所示。
mysql> DESC emp;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| name | varchar(20) | YES | | NULL | |
| phone | varchar(20) | YES | UNI | NULL | |
| addr | varchar(50) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
4 rows in set (0.01 sec)
从以上执行结果可看出,字段id的Key值为“PRI”,说明主键约束添加成功,phone字段的Key值为“UNI”,说明唯一约束添加成功,此时向emp表中添加数据进行验证,这里直接向表中插入两条数据,且phone字段的值相同,SQL语句如下所示。
mysql> INSERT INTO emp(
-> id,
-> name,
-> phone,
-> addr) VALUES(
-> 1,
-> 'zs',
-> 1366,
-> 'xxx'),(
-> 2,
-> 'ls',
-> 1366,
-> 'yyy');
ERROR 1062 (23000): Duplicate entry '1366' for key 'phone'
从以上执行结果可看出,由于添加两条数据的phone字段值相同,所以添加失败,这里只需要让两条数据的phone字段值不同即可,SQL语句如下所示。
mysql> INSERT INTO emp(
-> id,
-> name,
-> phone,
-> addr) VALUES(
-> 1,
-> 'zs',
-> 1366,
-> 'xxx'),(
-> 2,
-> 'ls',
-> 1591,
-> 'yyy');
Query OK, 2 rows affected (0.04 sec)
Records: 2 Duplicates: 0 Warnings: 0
以上执行结果证明插入数据完成,为了进一步验证,可以使用SELECT语句查看emp表中的数据,SQL语句如下所示。
mysql> SELECT * FROM emp;
+----+------+-------+------+
| id | name | phone | addr |
+----+------+-------+------+
| 1 | zs | 1366 | xxx |
| 2 | ls | 1591 | yyy |
+----+------+-------+------+
2 rows in set (0.02 sec)
从以上执行结果可看出,emp表中的数据成功插入,phone字段的值不相同,这就是唯一约束的作用,同样的,唯一约束也可以添加到已经创建完成的表中,语法格式如下所示。
ALTER TABLE 表名
ADD UNIQUE(列名);
接下来通过一个案例演示为已经创建完成的表添加唯一约束。
例5-4 创建学生表stu,创建完成后,为cid字段添加唯一约束,表结构如表5.3所示。
表5.3 stu表
字段 |
字段类型 |
说明 |
id |
INT |
学生编号 |
cid |
INT |
课程编号 |
name |
VARCHAR(20) |
员工姓名 |
首先创建stu表,SQL语句如下所示。
mysql> CREATE TABLE stu(
-> id INT,
-> cid INT,
-> name VARCHAR(20)
-> );
Query OK, 0 rows affected (0.09 sec)
以上执行结果证明表stu创建完成,接着为表中的cid列添加唯一约束,SQL语句如下所示。
mysql> ALTER TABLE stu
-> ADD UNIQUE(cid);
Query OK, 0 rows affected (0.24 sec)
Records: 0 Duplicates: 0 Warnings: 0
以上执行结果证明表stu中cid字段添加唯一约束成功,为了进一步验证,可以使用DESC查看表结构,SQL语句如下所示。
mysql> DESC stu;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| cid | int(11) | YES | UNI | NULL | |
| name | varchar(20) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.01 sec)
从以上执行结果可看出,表stu中cid字段成功添加了唯一约束。
5.1.3 自动增长列
在前面的学习中,数据表中的id字段一般从1开始插入,不断增加,这样做存在一些问题,添加数据时比较繁琐,每次都要添加一个id字段的值,而且这样做容易出错,为了解决这个问题,可以将id字段的值设置为自动增加,MySQL中使用AUTO_INCREMENT关键字设置表字段值自动增加,在创建表时将某个字段的值设置为自动增长,语法格式如下所示。
CREATE TABLE 表名(
字段名 数据类型 AUTO_INCREMENT,
……
);
以上语法格式中,字段名是要设置字段值自动增加的列名,列名后跟着数据类型和AUTO_INCREMENT关键字,之间用空格隔开,接下来通过一个案例演示自动增长列的用法。
例5-5 创建员工表emp2,并按表结构添加约束,表结构如表5.4所示。
表5.4 emp2表
字段 |
字段类型 |
约束 |
说明 |
id |
INT |
PRIMARY KEY AUTO_INCREMENT |
员工编号 |
name |
VARCHAR(20) |
|
员工姓名 |
phone |
VARCHAR(20) |
|
员工电话 |
表5.2中列出了emp2表的结构,包含三个字段,其中id字段需要添加主键约束并设置为自动增长的列,SQL语句如下所示。
mysql> CREATE TABLE emp2(
-> id INT PRIMARY KEY AUTO_INCREMENT,
-> name VARCHAR(20),
-> phone varchar(20)
-> );
Query OK, 0 rows affected (0.07 sec)
以上执行结果证明表emp2创建完成并添加约束和设置自动增长列,为了进一步验证,可以使用DESC查看表结构,SQL语句如下所示。
mysql> DESC emp2;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(20) | YES | | NULL | |
| phone | varchar(20) | YES | | NULL | |
+-------+-------------+------+-----+---------+----------------+
3 rows in set (0.01 sec)
从以上执行结果可看出,字段id的Key值为“PRI”,说明主键添加成功,Extra值为“auto_increment”,说明自动增长列设置成功,此时向emp2表中添加数据进行验证, SQL语句如下所示。
mysql> INSERT INTO emp2(
-> name,
-> phone)VALUES(
-> 'aa',
-> 1355);
Query OK, 1 row affected (0.04 sec)
以上执行结果证明数据添加成功,可以使用SELECT语句查看emp2表中的数据,SQL语句如下所示。
mysql> SELECT * FROM emp2;
+----+------+-------+
| id | name | phone |
+----+------+-------+
| 1 | aa | 1355 |
+----+------+-------+
1 row in set (0.00 sec)
从以上执行结果可看出,数据插入的同时,id字段自动生成了数值1,继续向emp2表中添加数据进行验证, SQL语句如下所示。
mysql> INSERT INTO emp2(
-> name,
-> phone)VALUES(
-> 'bb',
-> 1366);
Query OK, 1 row affected (0.04 sec)
以上执行结果证明数据添加成功,可以使用SELECT语句查看emp2表中的数据,SQL语句如下所示。
mysql> SELECT * FROM emp2;
+----+------+-------+
| id | name | phone |
+----+------+-------+
| 1 | aa | 1355 |
| 2 | bb | 1366 |
+----+------+-------+
2 rows in set (0.00 sec)
从以上执行结果可看出,第二条数据插入的同时,id字段自动生成了数值2,说明id字段成功设置了自动增长,同样的,自动增长列也可以为已经创建完成的表字段设置,语法格式如下所示。
ALTER TABLE 表名
MODIFY 字段名 数据类型 PRIMARY KEY AUTO_INCREMENT;
接下来通过一个案例演示为已经创建完成的表字段设置自动增长。
例5-6 创建教师表teacher,创建完成后,为id字段添加主键约束,并设置为自动增长的列,表结构如表5.5所示。
表5.5 teacher表
字段 |
字段类型 |
说明 |
id |
INT |
教师编号 |
name |
VARCHAR(20) |
教师姓名 |
phone |
VARCHAR(20) |
教师电话 |
首先创建teacher表,SQL语句如下所示。
mysql> use qianfeng3;
Database changed
mysql> CREATE TABLE teacher(
-> id INT,
-> name VARCHAR(20),
-> phone VARCHAR(20)
-> );
Query OK, 0 rows affected (0.09 sec)
以上执行结果证明表teacher创建完成,接着为id字段添加主键约束,并设置为自动增长的列,SQL语句如下所示。
mysql> ALTER TABLE teacher
-> MODIFY id INT PRIMARY KEY AUTO_INCREMENT;
Query OK, 0 rows affected (0.21 sec)
Records: 0 Duplicates: 0 Warnings: 0
以上执行结果证明表teacher中id字段添加主键约束成功,并设置为自动增长的列,为了进一步验证,可以使用DESC查看表结构,SQL语句如下所示。
mysql> DESC teacher;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(20) | YES | | NULL | |
| phone | varchar(20) | YES | | NULL | |
+-------+-------------+------+-----+---------+----------------+
3 rows in set (0.01 sec)
从以上执行结果可看出,id字段的Key值为PRI,Extra值为auto_increment,说明表teacher中id字段添加主键约束成功,并设置为自动增长的列。
5.2 索引
在现实生活中,去图书馆找一本感兴趣的书,如果从第一本开始依次找,明显效率是很慢的,这时应该按照书的分类来找,例如有的书柜放的是历史丛书,有的书柜放的是武侠小说等,MySQL中查找数据也有类似的问题,如果使用“SELECT * FROM表名 WHERE id=1000”,这就是数据库从第一条记录开始遍历,直到找到id等于1000的数据,这样明显效率非常低,MySQL提供了索引来解决这个问题。
在关系数据库中,索引是一种单独的、物理的对数据库表中一列或多列的值进行排序的一种存储结构,它是某个表中一列或若干列值的集合和相应的指向表中物理标识这些值的数据页的逻辑指针清单。索引的作用相当于图书的目录,可以根据目录中的页码快速找到所需的内容。MySQL中的索引分为很多种,包括普通索引、唯一索引、全文索引、单列索引、多列索引、空间索引、组合索引等,接下来详细讲解其中常用的普通索引和唯一索引。
5.2.1 普通索引
普通索引是最基本的索引类型,它的唯一任务是加快对数据的访问速度,因此,应该只为那些最经常出现在查询条件或排序条件中的数据列创建索引,尽可能选择一个数据最整齐、最紧凑的数据列来创建索引,例如一个整数数据类型的列。
在创建表时可以创建普通索引,语法格式如下所示。
CREATE TABLE 表名(
字段名 数据类型,
……
INDEX [索引名](字段名[(长度)])
);
以上语法格式中,INDEX用来表示字段的索引,索引名是可选值,括号中的字段名是创建索引的字段,参数长度是可选的,用于表示索引的长度。接下来通过一个案例演示普通索引的创建方法。
例5-7 创建测试表test1,并为id字段添加主键约束,为name字段创建普通索引,表结构如表5.6所示。
表5.6 test1表
字段 |
字段类型 |
id |
INT |
name |
VARCHAR(20) |
remark |
VARCHAR(50) |
创建表并添加约束和索引,SQL语句如下所示。
mysql> CREATE TABLE test1(
-> id INT PRIMARY KEY,
-> name VARCHAR(20),
-> remark VARCHAR(50),
-> INDEX(name)
-> );
Query OK, 0 rows affected (0.11 sec)
以上执行结果证明表test1创建完成,并添加了主键和普通索引,为了进一步验证,可以使用SHOW CREATE TABLE查看表的的具体信息,SQL语句如下所示。
mysql> SHOW CREATE TABLE test1\G;
*************************** 1. row ***************************
Table: test1
Create Table: CREATE TABLE `test1` (
`id` int(11) NOT NULL,
`name` varchar(20) DEFAULT NULL,
`remark` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
从以上执行结果可看出,id字段为主键,name字段创建了索引,说明表test1中id字段添加主键约束成功,name字段创建索引成功,这是创建表时同时创建普通索引,另外,已经创建完成的表,也可以为某个字段创建普通索引,语法格式如下所示。
CREATE INDEX 索引名 ON 表名(字段名[(长度)]);
接下来通过一个案例演示为已经创建完成的表字段创建普通索引。
例5-8 创建测试表test2,创建完成后,为id字段创建普通索引,表结构如表5.7所示。
表5.7 test2表
字段 |
字段类型 |
id |
INT |
name |
VARCHAR(20) |
remark |
VARCHAR(50) |
首先创建表test2,SQL语句如下所示。
mysql> CREATE TABLE test2(
-> id INT,
-> name VARCHAR(20),
-> remark VARCHAR(50)
-> );
Query OK, 0 rows affected (0.11 sec)
接着为表test2的id字段创建普通索引,SQL语句如下所示。
mysql> CREATE INDEX test2_id ON test2(id);
Query OK, 0 rows affected (0.16 sec)
Records: 0 Duplicates: 0 Warnings: 0
以上执行结果证明表test2的id字段普通索引创建完成,为了进一步验证,可以使用SHOW CREATE TABLE查看表的的具体信息,SQL语句如下所示。
mysql> SHOW CREATE TABLE test2\G;
*************************** 1. row ***************************
Table: test2
Create Table: CREATE TABLE `test2` (
`id` int(11) DEFAULT NULL,
`name` varchar(20) DEFAULT NULL,
`remark` varchar(50) DEFAULT NULL,
KEY `test2_id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
从以上执行结果可看出,id字段成功创建了索引,索引名称为test2_id。
5.2.2 唯一索引
前面讲解了普通索引,它允许被索引的数据列包含重复的值,例如姓名可能出现重复的情况,但有些值是不能重复的,在为这个数据列创建索引的时候就应该用关键字UNIQUE把它定义为一个唯一索引,这样做的好处有很多,一是简化MySQL对这个索引的管理工作,这个索引也因此而变得更有效率,二是MySQL会在有新记录插入数据表时,自动检查新记录的这个字段的值是否已经在某个记录的这个字段里出现过了,如果是,MySQL将拒绝插入那条新记录。也就是说,唯一索引可以保证数据记录的唯一性。
在创建表时可以创建唯一索引,语法格式如下所示。
CREATE TABLE 表名(
字段名 数据类型,
……
UNIQUE INDEX [索引名](字段名[(长度)])
);
以上语法格式中,UNIQUE INDEX关键字代表唯一索引,索引名是可选值,括号中的字段名是创建索引的字段,参数长度是可选的,用于表示索引的长度。接下来通过一个案例演示唯一索引的创建方法。
例5-9 创建测试表test3,并为id字段添加主键约束,为name字段创建唯一索引,表结构如表5.8所示。
表5.8 test3表
字段 |
字段类型 |
id |
INT |
name |
VARCHAR(20) |
remark |
VARCHAR(50) |
创建表并添加约束和索引,SQL语句如下所示。
mysql> CREATE TABLE test3(
-> id INT PRIMARY KEY,
-> name VARCHAR(20),
-> remark VARCHAR(50),
-> UNIQUE INDEX(name)
-> );
Query OK, 0 rows affected (0.07 sec)
以上执行结果证明表test3创建完成,并添加了主键和唯一索引,为了进一步验证,可以使用SHOW CREATE TABLE查看表的的具体信息,SQL语句如下所示。
mysql> SHOW CREATE TABLE test3\G;
*************************** 1. row ***************************
Table: test3
Create Table: CREATE TABLE `test3` (
`id` int(11) NOT NULL,
`name` varchar(20) DEFAULT NULL,
`remark` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
从以上执行结果可看出,id字段为主键,name字段创建了唯一索引,说明表test3中id字段添加主键约束成功,name字段创建唯一索引成功,这是创建表时同时创建唯一索引,另外,已经创建完成的表,也可以为某个字段创建唯一索引,语法格式如下所示。
CREATE UNIQUE INDEX 索引名 ON 表名(字段名[(长度)]);
接下来通过一个案例演示为已经创建完成的表字段创建唯一索引。
例5-10 创建测试表test4,创建完成后,为id字段创建唯一索引,表结构如表5.9所示。
表5.9 test4表
字段 |
字段类型 |
id |
INT |
name |
VARCHAR(20) |
remark |
VARCHAR(50) |
首先创建表test4,SQL语句如下所示。
mysql> CREATE TABLE test4(
-> id INT,
-> name VARCHAR(20),
-> remark VARCHAR(50)
-> );
Query OK, 0 rows affected (0.08 sec)
接着为表test4的id字段创建唯一索引,SQL语句如下所示。
mysql> CREATE UNIQUE INDEX test4_id ON test4(id);
Query OK, 0 rows affected (0.14 sec)
Records: 0 Duplicates: 0 Warnings: 0
以上执行结果证明表test4的id字段唯一索引创建完成,为了进一步验证,可以使用SHOW CREATE TABLE查看表的的具体信息,SQL语句如下所示。
mysql> SHOW CREATE TABLE test4\G;
*************************** 1. row ***************************
Table: test4
Create Table: CREATE TABLE `test4` (
`id` int(11) DEFAULT NULL,
`name` varchar(20) DEFAULT NULL,
`remark` varchar(50) DEFAULT NULL,
UNIQUE KEY `test4_id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
从以上执行结果可看出,id字段成功创建了唯一索引,索引名称为test4_id。
5.3 域完整性
域完整性是对关系中的单元格进行约束,域代表单元格,也就是对列的约束。域完整性约束包括数据类型、非空约束、默认值约束和check约束,数据类型在前面章节已经讲解过,check约束MySQL不支持,所以这里只讲解非空约束和默认值约束。
5.3.1 非空约束
非空约束用于保证数据表中某个字段的值不为NULL,MySQL中使用NOT NULL关键字添加非空约束,在创建表时,可以为某个字段添加非空约束,具体语法格式如下所示。
CREATE TABLE 表名(
字段名 数据类型 NOT NULL,
……
);
以上语法格式中,字段名是要添加非空约束的列名,列名后跟着数据类型和NOT NULL关键字,之间用空格隔开,接下来通过一个案例演示非空约束的用法。
例5-11 创建测试表test5,并按表结构添加约束,表结构如表5.10所示。
表5.10 test5表
字段 |
字段类型 |
约束 |
id |
INT |
PRIMARY KEY |
name |
VARCHAR(20) |
NOT NULL |
addr |
VARCHAR(50) |
|
表5.10中列出了test5表的结构,包含三个字段,其中id字段需要添加主键约束,name字段需要添加非空约束,SQL语句如下所示。
mysql> CREATE TABLE test5(
-> id INT PRIMARY KEY,
-> name VARCHAR(20) NOT NULL,
-> addr VARCHAR(50)
-> );
Query OK, 0 rows affected (0.07 sec)
以上执行结果证明表test5创建完成并添加约束,为了进一步验证,可以使用DESC查看表结构,SQL语句如下所示。
mysql> DESC test5;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| name | varchar(20) | NO | | NULL | |
| addr | varchar(50) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.01 sec)
从以上执行结果可看出,字段id的Key值为“PRI”,说明主键约束添加成功,字段name的Null列显示为“NO”,不可为NULL值,说明非空约束添加成功,此时向test5表中添加数据进行验证,SQL语句如下所示。
mysql> INSERT INTO test5(
-> id,
-> name,
-> addr)VALUES(
-> 1,
-> NULL,
-> 'xxx'
-> );
ERROR 1048 (23000): Column 'name' cannot be null
从以上执行结果可看出,由于添加name字段的值为NULL,所以添加失败,报出了“Column 'name' cannot be null”的错误。同样的,非空约束也可以添加到已经创建完成的表中,语法格式如下所示。
ALTER TABLE 表名
MODIFY 字段名 数据类型 NOT NULL;
接下来通过一个案例演示为已经创建完成的表添加非空约束。
例5-12 创建测试表test6,创建完成后,为id字段添加非空约束,表结构如表5.11所示。
表5.11 test6表
字段 |
字段类型 |
id |
INT |
name |
VARCHAR(20) |
addr |
VARCHAR(50) |
首先创建test6表,SQL语句如下所示。
mysql> CREATE TABLE test6(
-> id INT,
-> name VARCHAR(20),
-> addr VARCHAR(50)
-> );
Query OK, 0 rows affected (0.08 sec)
以上执行结果证明表test6创建完成,接着为表中的id列添加非空约束,SQL语句如下所示。
mysql> ALTER TABLE test6
-> MODIFY id INT NOT NULL;
Query OK, 0 rows affected (0.20 sec)
Records: 0 Duplicates: 0 Warnings: 0
以上执行结果证明表test6中id字段添加非空约束成功,为了进一步验证,可以使用DESC查看表结构,SQL语句如下所示。
mysql> DESC test6;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | NO | | NULL | |
| name | varchar(20) | YES | | NULL | |
| addr | varchar(50) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.01 sec)
从以上执行结果可看出,表test6中id字段NULL列的值为NO,证明成功添加了非空约束。
5.3.2 默认值约束
默认值约束用于为数据表中某个字段的值添加默认值,例如订单的创建时间,如果不进行手动填写,可以设置创建时间字段的默认值为当前时间,MySQL中使用DEFAULT关键字添加默认值约束,在创建表时,可以为某个字段添加默认值约束,具体语法格式如下所示。
CREATE TABLE 表名(
字段名 数据类型 DEFAULT 默认值,
……
);
以上语法格式中,字段名是要添加默认值约束的列名,列名后跟着数据类型和DEFAULT关键字,DEFAULT是添加的默认值,之间用空格隔开,接下来通过一个案例演示默认值约束的用法。
例5-13 创建测试表test7,并按表结构添加约束,表结构如表5.12所示。
表5.12 test7表
字段 |
字段类型 |
约束 |
id |
INT |
PRIMARY KEY |
name |
VARCHAR(20) |
|
addr |
VARCHAR(50) |
DEFAULT 'ABC' |
表5.12中列出了test7表的结构,包含三个字段,其中id字段需要添加主键约束,addr字段需要添加默认值约束,SQL语句如下所示。
mysql> CREATE TABLE test7(
-> id INT PRIMARY KEY,
-> name VARCHAR(20),
-> addr VARCHAR(50) DEFAULT 'ABC'
-> );
Query OK, 0 rows affected (0.08 sec)
以上执行结果证明表test7创建完成并添加约束,为了进一步验证,可以使用DESC查看表结构,SQL语句如下所示。
mysql> DESC test7;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| name | varchar(20) | YES | | NULL | |
| addr | varchar(50) | YES | | ABC | |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.02 sec)
从以上执行结果可看出,字段id的Key值为“PRI”,说明主键约束添加成功,字段addr的Default值为“ABC”,说明默认值约束添加成功,此时向test7表中添加数据进行验证,SQL语句如下所示。
mysql> INSERT INTO test7(
-> id,
-> name)VALUES(
-> 1,
-> 'zs'
-> );
Query OK, 1 row affected (0.05 sec)
以上执行结果证明表test7添加了一条数据,且只添加了id和name两个字段的值,这时可以查看表中数据,SQL语句如下所示。
mysql> SELECT * FROM test7;
+----+------+------+
| id | name | addr |
+----+------+------+
| 1 | zs | ABC |
+----+------+------+
1 row in set (0.00 sec)
从以上执行结果可看出,表test7中addr字段使用了默认值“ABC”,证明默认值约束添加成功。同样的,默认值约束也可以添加到已经创建完成的表中,语法格式如下所示。
ALTER TABLE 表名
MODIFY 字段名 数据类型 DEFAULT 默认值;
接下来通过一个案例演示为已经创建完成的表添加默认值约束。
例5-14 创建测试表test8,创建完成后,为name字段添加默认值约束,默认值为“lilei”,表结构如表5.13所示。
表5.13 test8表
字段 |
字段类型 |
id |
INT |
name |
VARCHAR(20) |
addr |
VARCHAR(50) |
首先创建test8表,SQL语句如下所示。
mysql> CREATE TABLE test8(
-> id INT,
-> name VARCHAR(20),
-> addr VARCHAR(50)
-> );
Query OK, 0 rows affected (0.08 sec)
以上执行结果证明表test8创建完成,接着为表中的name字段添加默认值约束,SQL语句如下所示。
mysql> ALTER TABLE test8
-> MODIFY name VARCHAR(20) DEFAULT 'lilei';
Query OK, 0 rows affected (0.05 sec)
Records: 0 Duplicates: 0 Warnings: 0
以上执行结果证明表test8中name字段添加默认值约束成功,为了进一步验证,可以使用DESC查看表结构,SQL语句如下所示。
mysql> DESC test8;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| name | varchar(20) | YES | | lilei | |
| addr | varchar(50) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
从以上执行结果可看出,表test8中name字段Default列的值为“lilei”,证明成功添加了默认值约束。
5.4 引用完整性
引用完整性是对实体之间关系的描述,是定义外关键字与主关键字之间的引用规则,也就是外键约束,如果要删除被引用的对象,那么也要删除引用它的所有对象,或者把引用值设置为空,接下来将详细讲解外键约束的有关内容。
5.4.1 什么是外键
外键是指引用另一个表中的一列或多列,被引用的列应该具有主键约束或唯一约束,外键用于建立和加强两个表数据之间的连接,接下来通过两张表讲解什么是外键约束。
首先创建学科表subject,包含两个字段,专业编号sub_id和专业名称sub_name,SQL语句如下所示。
mysql> CREATE TABLE subject(
-> sub_id INT PRIMARY KEY,
-> sub_name VARCHAR(20)
-> );
Query OK, 0 rows affected (0.35 sec)
接着创建学生表student,包含三个字段,学生编号stu_id、学生姓名stu_name和专业编号sub_id,SQL语句如下所示。
mysql> CREATE TABLE student(
-> stu_id INT PRIMARY KEY,
-> stu_name VARCHAR(20),
-> sub_id INT NOT NULL
-> );
Query OK, 0 rows affected (0.16 sec)
创建的subject表中sub_id为主键,在student表中也有sub_id字段,这里是引入了subject表的主键,那么student表中的sub_id字段就是外键,被引用的表subject是主表,引用外键的表student是从表,两个表是主从关系,表student可以通过sub_id连接表subject中的信息,从而建立两个表数据之间的连接。
由于student表中的sub_id字段是外键,所以当外键字段引用了主表subject的数据时,subject表不允许单方面删除表或表中数据,需要先删除引用它的所有对象,或者把引用值设置为空,接下来验证这种情况。
首先为主表subject添加数据,SQL语句如下所示。
mysql> INSERT INTO subject(
-> sub_id,
-> sub_name) VALUES(
-> 1,
-> 'math'
-> );
Query OK, 1 row affected (0.08 sec)
以上执行结果证明插入数据完成,为了进一步验证,可以使用SELECT语句查看subject表中的数据,SQL语句如下所示。
mysql> SELECT * FROM subject;
+--------+----------+
| sub_id | sub_name |
+--------+----------+
| 1 | math |
+--------+----------+
1 row in set (0.03 sec)
从以上执行结果可看出,subject表中的数据成功插入,接着向student表插入数据,SQL语句如下所示。
mysql> INSERT INTO student(
-> stu_id,
-> stu_name,
-> sub_id) VALUES(
-> 1,
-> 'zs',
-> 1
-> );
Query OK, 1 row affected (0.05 sec)
以上执行结果证明插入数据完成,为了进一步验证,可以使用SELECT语句查看student表中的数据,SQL语句如下所示。
mysql> SELECT * FROM student;
+--------+----------+--------+
| stu_id | stu_name | sub_id |
+--------+----------+--------+
| 1 | zs | 1 |
+--------+----------+--------+
1 row in set (0.00 sec)
从以上执行结果可看出,student表中的数据成功插入,表中的sub_id为1,是引用了subject表中sub_id字段的值,这时如果删除主表subject中的数据,SQL语句如下所示。
mysql> DELETE FROM subject;
Query OK, 1 row affected (0.07 sec)
从以上执行结果可看出,表subject中的数据删除成功,这明显不符合外键约束的作用,数据被从表引用时,主表中的数据不应该被删除,这是因为此时还没有为sub_id字段添加外键约束,接下来会详细讲解如何添加外键约束。
5.4.2 添加外键约束
前面讲解了外键约束是什么,为什么需要外键约束,若想真正连接两个表的数据,就需要为表添加外键约束,语法格式如下所示。
ALTER TABLE 表名 ADD FOREIGN KEY(外键字段名)
REFERENCES 主表表名(主键字段名);
接下来依然使用前面创建的student表和subject表,并清空两张表的数据,这里就不再演示,为student表中的sub_id字段添加外键约束,SQL语句如下所示。
mysql> ALTER TABLE student
-> ADD FOREIGN KEY(sub_id)
-> REFERENCES subject(sub_id);
Query OK, 0 rows affected (0.22 sec)
Records: 0 Duplicates: 0 Warnings: 0
以上执行结果证明添加外键约束成功,此时,如果先为student表添加数据,是无法添加的,因为subject表中还没有可以引用的数据,SQL语句如下所示。
mysql> INSERT INTO student(
-> stu_id,
-> stu_name,
-> sub_id) VALUES(
-> 1,
-> 'zs',
-> 1
-> );
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint
fails (`qianfeng3`.`student`, CONSTRAINT `student_ibfk_1` FOREIGN KEY (
`sub_id`) REFERENCES `subject` (`sub_id`))
从以上执行结果可看出,主表中没有数据,从表中无法插入数据,此时先为subject表插入数据,SQL语句如下所示。
mysql> INSERT INTO subject(
-> sub_id,
-> sub_name) VALUES(
-> 1,
-> 'math'
-> );
Query OK, 1 row affected (0.08 sec)
以上执行结果证明插入数据完成,接着为student表插入数据,SQL语句如下所示。
mysql> INSERT INTO student(
-> stu_id,
-> stu_name,
-> sub_id) VALUES(
-> 1,
-> 'zs',
-> 1
-> );
Query OK, 1 row affected (0.05 sec)
以上执行结果证明插入数据完成,接下来依然进行前面的实验,直接删除subject表中的数据,SQL语句如下所示。
mysql> DELETE FROM subject;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign
key constraint fails (`qianfeng3`.`student`, CONSTRAINT
`student_ibfk_1` FOREIGN KEY (`sub_id`) REFERENCES `subject`
(`sub_id`))
从以上执行结果可看出,由于表subject中的数据被student表引用,所以无法删除subject表中的数据,此时可以先删除从表中的数据,再删除主表中的数据,首先删除student表中的数据,SQL语句如下所示。
mysql> DELETE FROM student;
Query OK, 1 row affected (0.03 sec)
以上执行结果证明student表中数据删除成功,接着删除主表subject中的数据,SQL语句如下所示。
mysql> DELETE FROM subject;
Query OK, 1 row affected (0.03 sec)
以上执行结果证明subject表中数据删除成功,这就是外键约束的基本使用,除了创建表完成后添加外键约束,在创建表的同时也可以添加外键约束,语法格式如下所示。
CREATE TABLE 表名(
字段名 数据类型,
……,
FOREIGN KEY(外键字段名)
REFERENCES 主表表名(主键字段名)
);
接下来通过一个案例演示创建表的同时添加外键约束,创建学生表student2和分数表score,其中学生表包含两个字段,分别为学生编号stu_id和学生姓名stu_name,分数表包括三个字段,分别为分数编号sco_id、分数score和学生编号stu_id,首先创建学生表,SQL语句如下所示。
mysql> CREATE TABLE student2(
-> stu_id INT PRIMARY KEY,
-> stu_name VARCHAR(20)
-> );
Query OK, 0 rows affected (0.08 sec)
以上执行结果证明student2表创建成功,接着创建分数表,创建的同时添加外键约束,SQL语句如下所示。
mysql> CREATE TABLE score(
-> sco_id INT PRIMARY KEY,
-> score INT,
-> stu_id INT,
-> FOREIGN KEY(stu_id)
-> REFERENCES student2(stu_id)
-> );
Query OK, 0 rows affected (0.09 sec)
以上执行结果证明score表创建成功,创建的同时添加了外键约束,为了进一步验证,可以使用SHOW CREATE TABLE语句查看score表,SQL语句如下所示。
mysql> SHOW CREATE TABLE score\G;
*************************** 1. row ***************************
Table: score
Create Table: CREATE TABLE `score` (
`sco_id` int(11) NOT NULL,
`score` int(11) DEFAULT NULL,
`stu_id` int(11) DEFAULT NULL,
PRIMARY KEY (`sco_id`),
KEY `stu_id` (`stu_id`),
CONSTRAINT `score_ibfk_1` FOREIGN KEY (`stu_id`) REFERENCES
`student2` (`stu_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
从以上执行结果可看出,score表的stu_id字段有外键约束,关联的主表为student2。
5.4.3 删除外键约束
前面讲解了添加外键约束的两种方式,在实际开发中,有可能会出现需要解除两个表之间的关联关系,这就需要用到删除外键约束,语法格式如下所示。
ALTER TABLE 表名 DROP FOREIGN KEY 外键名;
接下来演示将表student中的外键约束删除,首先查看表中的外键名,SQL语句如下所示。
mysql> SHOW CREATE TABLE student\G;
*************************** 1. row ***************************
Table: student
Create Table: CREATE TABLE `student` (
`stu_id` int(11) NOT NULL,
`stu_name` varchar(20) DEFAULT NULL,
`sub_id` int(11) NOT NULL,
PRIMARY KEY (`stu_id`),
KEY `sub_id` (`sub_id`),
CONSTRAINT `student_ibfk_1` FOREIGN KEY (`sub_id`) REFERENCES `subject`
(`sub_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
从以上执行结果可看出,sub_id字段为外键,关联的主表是subject,外键名为student_ibfk_1,接着下来删除这个外键约束,SQL语句如下所示。
mysql> ALTER TABLE student DROP FOREIGN KEY student_ibfk_1;
Query OK, 0 rows affected (0.16 sec)
Records: 0 Duplicates: 0 Warnings: 0
以上执行结果证明student表的外键约束删除成功,为了进一步验证,可以使用SHOW CREATE TABLE语句查看student表,SQL语句如下所示。
mysql> SHOW CREATE TABLE student\G;
*************************** 1. row ***************************
Table: student
Create Table: CREATE TABLE `student` (
`stu_id` int(11) NOT NULL,
`stu_name` varchar(20) DEFAULT NULL,
`sub_id` int(11) NOT NULL,
PRIMARY KEY (`stu_id`),
KEY `sub_id` (`sub_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
从以上执行结果可看出,student表的外键约束删除成功。
5.5 本章小结
本章首先介绍了实体完整性,重点讲解了主键约束、唯一约束和自动增长列,然后介绍了索引,索引中举例讲解了普通索引和唯一索引,接着讲解了域完整性,重点讲解其中的非空约束和默认值约束,最后讲解了引用完整性,大家需要多理解引用完整性,便于后面多表查询的学习。
5.6 习题
1.思考题
(1) 请简述实体完整性有哪些。
(2) 请简述索引分为哪几类。
(3) 请简述索引的作用。
(4) 请简述域完整性有哪些。
(5) 请简述引用完整性的作用。
- 点赞
- 收藏
- 关注作者
评论(0)