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表的完整性约束的主要内容,如果未能解决你的问题,请参考以下文章