132 MySQL表的完整性约束

Posted xichenhome

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了132 MySQL表的完整性约束相关的知识,希望对你有一定的参考价值。

一、表的完整性约束目的

  • 为了防止不符合规范的数据进入数据库,在用户对数据进行插入、修改、删除等操作时,DBMS自动按照一定的约束条件对数据进行监测,使不符合规范的数据不能进入数据库,以确保数据库中存储的数据正确、有效、相容。

  • 约束条件与数据类型的宽度一样,都是可选参数,主要分为以下几种:
    • not null : 非空约束,指定某列不能为空
    • auto_increment : 自增约束,只用在int型
    • unique : 字段唯一性约束,指定某列或几列的数据不能重复
    • primary key : 主键,指定该列的值可以唯一地标识该列记录
    • forrign key : 外键,指定该行记录从属于主表中的一条记录,主要用于参照完整性

二、not null

是否可空,null表示空,非字符串

not null - 不可空

null - 可空

2.1 not null 实例

1.创建t12表 id字段约束不为空
mysql> create table t12 (id int not null);
Query OK, 0 rows affected (0.02 sec)

2.查看t12表中所有字段记录
mysql> select * from t12;
Empty set (0.00 sec)

3.显示t12表的结构
mysql> desc t12;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id    | int(11) | NO   |     | NULL    |       |
+-------+---------+------+-----+---------+-------+
row in set (0.00 sec)

4.不能向id列插入空元素,插入的是空值
mysql> insert into t12 values (null);
ERROR 1048 (23000): Column 'id' cannot be null

5.向t12表中插入正确数据
mysql> insert into t12 values (1);
Query OK, 1 row affected (0.01 sec)

2.2 default

我们约束了某一列不为空,如果这一列中经常有重复的内容,就需要我们频繁的插入,这样会给我们的操作带来新的负担,于是就出现了默认值的概念。

默认值,创建列时可以指定默认值,当插入数据时如果未主动设置,则自动添加默认值。

2.3 not null + default实例

1.创建t13表 id1字段约束不为空,id2字段约束不为空且默认值为222
mysql> create table t13 (id1 int not null,id2 int not null default 222);
Query OK, 0 rows affected (0.01 sec)

2.显示t13表结构
mysql> desc t13;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id1   | int(11) | NO   |     | NULL    |       |
| id2   | int(11) | NO   |     | 222     |       |
+-------+---------+------+-----+---------+-------+
rows in set (0.01 sec)

3.只向id1字段添加值,会发现id2字段会使用默认值填充
mysql> insert into t13 (id1) values (111);
Query OK, 1 row affected (0.00 sec)

4.显示当前表的记录
mysql> select * from t13;
+-----+-----+
| id1 | id2 |
+-----+-----+
| 111 | 222 |
+-----+-----+
row in set (0.00 sec)

5.id1字段不能为空,所以不能单独向id2字段填充值;
mysql> insert into t13 (id2) values (223);
ERROR 1364 (HY000): Field 'id1' doesn't have a default value

6.向id1,id2中分别填充数据,id2的填充数据会覆盖默认值
mysql> insert into t13 (id1,id2) values (112,223);
Query OK, 1 row affected (0.00 sec)
mysql> select * from t13;
+-----+-----+
| id1 | id2 |
+-----+-----+
| 111 | 222 |
| 112 | 223 |
+-----+-----+
rows in set (0.00 sec)

2.4 not null 不生效

设置严格模式:
    不支持对not null字段插入null值
    不支持对自增长字段插入”值
    不支持text字段有默认值

直接在mysql中生效(重启失效):
mysql>set sql_mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION";

配置文件添加(永久失效):
sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"

三、auto_increment

  • 设置字段的值在没有被赋值时自增,只用于int型,并且字段必须设置为键字段

  • 被约束的字段必须同时被key约束
  • 一个表只能由一个自增字段

3.1 实例

1.创建学生表不指定id,则自动增长
create table student(
id int unique auto_increment,
name varchar(20),
sex enum('male','female') default 'male'
);

mysql> desc student;
+-------+-----------------------+------+-----+---------+----------------+
| Field | Type                  | Null | Key | Default | Extra          |
+-------+-----------------------+------+-----+---------+----------------+
| id    | int(11)               | NO   | PRI | NULL    | auto_increment |
| name  | varchar(20)           | YES  |     | NULL    |                |
| sex   | enum('male','female') | YES  |     | male    |                |
+-------+-----------------------+------+-----+---------+----------------+
mysql> insert into student(name) values
    -> ('cecilia'),
    -> ('xichen')
    -> ;

mysql> select * from student;
+----+----------+------+
| id | name     | sex  |
+----+----------+------+
|  1 | cecilia  | male |
|  2 | xichen   | male |
+----+----------+------+


2. 也可以指定id
mysql> insert into student values(4,'asb','female');
Query OK, 1 row affected (0.00 sec)

mysql> insert into student values(7,'wsb','female');
Query OK, 1 row affected (0.00 sec)

mysql> select * from student;
+----+---------+--------+
| id | name    | sex    |
+----+---------+--------+
|  1 | cecilia | male   |
|  2 | xichen  | male   |
|  4 | asb     | female |
|  7 | wsb     | female |
+----+---------+--------+


3. 对于自增的字段,在用delete删除后,再插入值,该字段仍按照删除前的位置继续增长
mysql> delete from student;
Query OK, 4 rows affected (0.00 sec)

mysql> select * from student;
Empty set (0.00 sec)

mysql> insert into student(name) values('ysb');
mysql> select * from student;
+----+------+------+
| id | name | sex  |
+----+------+------+
|  8 | ysb  | male |
+----+------+------+

4. 应该用truncate清空表,比起delete一条一条地删除记录,truncate是直接清空表,在删除大表时用它
mysql> truncate student;
Query OK, 0 rows affected (0.01 sec)

mysql> insert into student(name) values('xichen');
Query OK, 1 row affected (0.01 sec)

mysql> select * from student;
+----+--------+------+
| id | name   | sex  |
+----+--------+------+
|  1 | xichen | male |
+----+--------+------+
row in set (0.00 sec)

四、unique

唯一约束,指定某列或者几列组合不能重复。

4.1 unique实例

方法一:
create table t1(
id int,
name varchar(20) unique,
course varchar(100)
);


方法二:
create table department2(
id int,
name varchar(20),
course varchar(100),
unique(name)
);


mysql> insert into t1 values(1,'xichen','计算机');
Query OK, 1 row affected (0.00 sec)
mysql> insert into t1 values(1,'xichenT','计算机'); # 此时会报错
ERROR 1062 (23000): Duplicate entry 'IT' for key 'name'

4.2 联合唯一

  • ip在port不同时,可以相同,ip不同时port也可以相同,均合法
  • ip和port都相同时,就是重复数据,不合法
mysql>: create table tu1 (
    ip char(16), 
    port int, 
    unique(ip, port)# 联合唯一
);
    

# 插入正确数据
mysql> insert into service values
    -> ('192.168.0.10',8080),
    -> ('192.168.0.20',8080),
    -> ('192.168.0.30',3306)
    -> ;
Query OK, 3 rows affected (0.01 sec)
Records: 3  Duplicates: 0  Warnings: 0
            

# 插入重复数据 (ip,poor和已有的记录重复了)
mysql> insert into service(name,host,port) values('192.168.0.10',8080);
ERROR 1062 (23000): Duplicate entry '192.168.0.10-8080' for key 'host'

五、primary key

  • 表都会拥有,不设置为默认找第一个 不空,唯一 字段,未标识则创建隐藏字段
  • 主键为了保证表中的每一条数据的该字段都是表格中的唯一值。换言之,它是用来独一无二地确认一个表格中的每一行数据。
  • 主键可以包含一个字段或多个字段。当主键包含多个栏位时,称为组合键 (Composite Key),也可以叫联合主键。
  • 主键可以在建置新表格时设定 (运用 CREATE TABLE 语句),或是以改变现有的表格架构方式设定 (运用 ALTER TABLE)。
  • 主键必须唯一,主键值非空;可以是单一字段,也可以是多字段组合。

5.1 单字段做主键

#方法一:not null+unique
create table t1(
id int not null unique, #主键 默认找第一个设为唯一键的字段
name varchar(20) not null unique,
course varchar(100)
);

mysql> desc t1;
+---------+--------------+------+-----+---------+-------+
| Field   | Type         | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+-------+
| id      | int(11)      | NO   | PRI | NULL    |       |
| name    | varchar(20)  | NO   | UNI | NULL    |       |
| course  | varchar(100) | YES  |     | NULL    |       |
+---------+--------------+------+-----+---------+-------+
rows in set (0.01 sec)


#方法二:在某一个字段后用primary key
create table t2(
id int primary key, #主键
name varchar(20),
course varchar(100)
);

mysql> desc t2;
+---------+--------------+------+-----+---------+-------+
| Field   | Type         | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+-------+
| id      | int(11)      | NO   | PRI | NULL    |       |
| name    | varchar(20)  | YES  |     | NULL    |       |
| course  | varchar(100) | YES  |     | NULL    |       |
+---------+--------------+------+-----+---------+-------+
rows in set (0.00 sec)

#方法三:在所有字段后单独定义primary key
create table t3(
id int,
name varchar(20),
course varchar(100),
primary key(id); #字段id设为主键

mysql> desc t3;
+---------+--------------+------+-----+---------+-------+
| Field   | Type         | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+-------+
| id      | int(11)      | NO   | PRI | NULL    |       |
| name    | varchar(20)  | YES  |     | NULL    |       |
| course | varchar(100) | YES  |     | NULL    |       |
+---------+--------------+------+-----+---------+-------+
rows in set (0.01 sec)

# 方法四:给已经建成的表添加主键约束
mysql> create table t4(
    -> id int,
    -> name varchar(20),
    -> course varchar(100));
Query OK, 0 rows affected (0.01 sec)

mysql> desc t4;
+---------+--------------+------+-----+---------+-------+
| Field   | Type         | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+-------+
| id      | int(11)      | YES  |     | NULL    |       |
| name    | varchar(20)  | YES  |     | NULL    |       |
| course  | varchar(100) | YES  |     | NULL    |       |
+---------+--------------+------+-----+---------+-------+
rows in set (0.01 sec)

# 给已经建成的表添加主键约束
mysql> alter table t4 modify id int primary key;
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc t4;
+---------+--------------+------+-----+---------+-------+
| Field   | Type         | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+-------+
| id      | int(11)      | NO   | PRI | NULL    |       |
| name    | varchar(20)  | YES  |     | NULL    |       |
| course  | varchar(100) | YES  |     | NULL    |       |
+---------+--------------+------+-----+---------+-------+
rows in set (0.01 sec)

5.2 多字段做主键(主键唯一)

# 创建多字段做主键(ip,port)
create table t1(
ip varchar(15),
port char(5),
name varchar(10) not null,
primary key(ip,port)
);


mysql> desc service;
+--------------+-------------+------+-----+---------+-------+
| Field        | Type        | Null | Key | Default | Extra |
+--------------+-------------+------+-----+---------+-------+
| ip           | varchar(15) | NO   | PRI | NULL    |       |
| port         | char(5)     | NO   | PRI | NULL    |       |
| name         | varchar(10) | NO   |     | NULL    |       |
+--------------+-------------+------+-----+---------+-------+
rows in set (0.00 sec)

# 插入两条数据
mysql> insert into t1 values
    -> ('172.16.45.10','3306','mysqld'),
    -> ('172.16.45.11','3306','mariadb')
    -> ;
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> insert into t1 values ('172.16.45.10','3306','nginx');
ERROR 1062 (23000): Duplicate entry '172.16.45.10-3306' for key 'PRIMARY'

5.3 主键和唯一键分析

1.x为主键:没有设置primary key时,第一个 唯一自增键,会自动提升为主键
mysql>: create table t1 (x int unique auto_increment, y int unique);
    
2.y为主键:没有设置primary key时,第一个 唯一自增键,会自动提升为主键
mysql>: create table t2 (x int unique, y int unique auto_increment);
    
3.x为主键:设置了主键就是设置的,主键没设置自增,那自增是可以设置在唯一键上的
mysql>: create table t3 (x int primary key, y int unique auto_increment);
    
4.x为主键:设置了主键就是设置的,主键设置了自增,自增字段只能有一个,所以唯一键不能再设置自增了
mysql>: create table t4 (x int primary key auto_increment, y int unique);
    
5.默认主键:没有设置主键,也没有 唯一自增键,那系统会默认添加一个 隐式主键(不可见)
mysql>: create table t5 (x int unique, y int unique);

以上是关于132 MySQL表的完整性约束的主要内容,如果未能解决你的问题,请参考以下文章

MySQL表的完整性约束

mysql表的完整性约束

mysql—表的完整性约束

mysql—表的完整性约束

mysql表的完整性约束

MySQL表的完整性约束