mysql唯一约束

Posted

tags:

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

参考技术A 唯一约束  unique

特征:

1.不允许有重复的值,保证数据的唯一性。

2.可以有空值

3.在一个表中,可以有多个唯一约束

4.默认情况下,唯一约束的名字和列名保持一致

5.添加唯一约束的列,系统也会默认给这个列添加一个唯一索引

索引:等同于书本的目录,将来能够加快数据的查询速度。

如何添加唯一约束

1.创建表的同时创建唯一约束 UN_列名

格式一:

create table 表名(

列名1 数据类型,

列名2 数据类型,

constraint 唯一约束的名字 unique(列名1),

constraint 唯一约束的名字 unique(列名2)

);

格式二:

create table 表名(

列名1 数据类型 unique,

列名2 数据类型 unique,

列名3 数据类型

);

一个表中是可以存在多个约束的

2.针对已经存在的表,添加唯一约束

格式:

alter table 表名 add unique(列名[,列名2]);

3.删除唯一约束

格式:

alter table 表名 drop index 唯一约束的名字;

Linux学习-MySQL约束

MySQL约束

MySQL约束为保证数据记录完整性定义的一系列规则、限定。

约束分类

| 唯一性约束 | UNIQUE KEY |
|主键约束| PRIMARY KEY|
|非空约束| NOT NULL|
|自增列| AUTO_INCREMENT|
|外键约束| FOREIGN KEY|
|默认值约束| DEFAULT|
|检查约束| check|

UNIQUE唯一性约束
唯一性约束:列值必须唯一,但可以为空值(空值可以重复)
 1. 添加唯一性约束的列上会自动创建唯一索引
 2. 删除唯一性约束只能通过删除唯一索引的方式删除
 3. 删除时需要指定唯一索引名称,唯一索引名称同唯一约束名
 4. 如果创建唯一约束时未指定名称,如果是单列,默认名称同列名,如组合列,默认与()中排第一的列值相同,也可以自定义唯一约束名称。
PRIMARY KEY主键约束
主键约束:用于唯一标识表中的一行记录,唯一约束+非空约束的组合
 1. 一个表中最多只能有一个主键约束,建立主键约束可以在列级别,也可在表级别
 2. 主键约束对应着表中的一列或多列(复合主键)
 3. 如果多列组合复合主键约束,那么这些列都不允许为空,并且组合的值不能重复
 4. MySQL主键名是PRIMARY
 5. 当创建主键约束时,系统默认会在所在的列或列组合上建立对应的主键索引(主键查询效率更高),主键约束删除,对应的索引也自动删除
 6. 不要修改主键字段的值,因为主键是数据记录的唯一标识,如果修改了主键的值,就可能破坏数据的完整性

#创建列级主键约束
mysql> create table test3(id int primary key,last_name varchar(20),email varchar(25),salary decimal(10,2));
Query OK, 0 rows affected (0.01 sec)

mysql> desc test3;
+-----------+---------------+------+-----+---------+-------+
| Field     | Type          | Null | Key | Default | Extra |
+-----------+---------------+------+-----+---------+-------+
| id        | int           | NO   | PRI | NULL    |       |
| last_name | varchar(20)   | YES  |     | NULL    |       |
| email     | varchar(25)   | YES  |     | NULL    |       |
| salary    | decimal(10,2) | YES  |     | NULL    |       |
+-----------+---------------+------+-----+---------+-------+
4 rows in set (0.01 sec)

mysql> select * from information_schema.table_constraints where table_name='test3';
+--------------------+-------------------+-----------------+--------------+------------+-----------------+----------+
| CONSTRAINT_CATALOG | CONSTRAINT_SCHEMA | CONSTRAINT_NAME | TABLE_SCHEMA | TABLE_NAME | CONSTRAINT_TYPE | ENFORCED |
+--------------------+-------------------+-----------------+--------------+------------+-----------------+----------+
| def                | dbtest13          | PRIMARY         | dbtest13     | test3      | PRIMARY KEY     | YES      |
+--------------------+-------------------+-----------------+--------------+------------+-----------------+----------+
1 row in set (0.01 sec)
mysql> show index from test3;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| test3 |          0 | PRIMARY  |            1 | id          | A         |           0 |     NULL |   NULL |      | BTREE      |         |               | YES     | NULL       |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
1 row in set (0.01 sec)

#创建表级主键约束
mysql> create table test5(id int,last_name varchar(20),email varchar(25),salary decimal(10,2),primary key(id));
Query OK, 0 rows affected (0.01 sec)

mysql> desc test5;
+-----------+---------------+------+-----+---------+-------+
| Field     | Type          | Null | Key | Default | Extra |
+-----------+---------------+------+-----+---------+-------+
| id        | int           | NO   | PRI | NULL    |       |
| last_name | varchar(20)   | YES  |     | NULL    |       |
| email     | varchar(25)   | YES  |     | NULL    |       |
| salary    | decimal(10,2) | YES  |     | NULL    |       |
+-----------+---------------+------+-----+---------+-------+
4 rows in set (0.00 sec)

mysql> select * from information_schema.table_constraints where table_name='test5';
+--------------------+-------------------+-----------------+--------------+------------+-----------------+----------+
| CONSTRAINT_CATALOG | CONSTRAINT_SCHEMA | CONSTRAINT_NAME | TABLE_SCHEMA | TABLE_NAME | CONSTRAINT_TYPE | ENFORCED |
+--------------------+-------------------+-----------------+--------------+------------+-----------------+----------+
| def                | dbtest13          | PRIMARY         | dbtest13     | test5      | PRIMARY KEY     | YES      |
+--------------------+-------------------+-----------------+--------------+------------+-----------------+----------+
1 row in set (0.00 sec)
AUTO_INCREMENT自增
自增:某个字段的值自增
 1. 一个表最多只能有一个自增长列
 2. 当需要产生唯一标识符或顺序值时,可设置自增长
 3. 自增长列约束必须是键值(主键列,唯一键列)
 4. 自增约束的列数据类型必须为整型
 5. 如果自增列指定了0和NULL,会在当前最大值的基础上自增;如果自增列手动指定了具体值,直接赋值为具体值
#通过修改MySQL变量可以变更自增值
mysql> set auto_increment_increment=4;
#当像含有AUTO_INCREMENT的字段上添加0或null时,实际上会自动往上添加指定的值,在开发中向含有AUTO_INCREMENT的字段上插入数据时,不需要向此列中赋值。
#注:
(MySQL5.7)AUTO_INCREMENT在内存中维护着一个值,删除数据后,重启服务器后,会根据数据库表中的记录重新生成值
MySQL8.0将自增的计数器持久化到重做日志中,每次计数发生改变,都会将其写入重做日志中,如果数据库重启,InnoDB会根据重做日志中的信息来初使化计数器的内存值。
FOREIGN KEY外键约束
外键约束:限定某个表的某个字段的引用完整性
 1. 主表(父表):被引用的表,被参考的表
 2. 从表(子表):引用别人的表,参考别人的表
 3. 从表的外键列必须引用/参考主表的主键或唯一约束列
 4. 在创建外键约束时,如果不给外键约束命名,默认不是列名,而是自动产生一个外键名,也可以指定外键约束名
 5. 创建表时指定外键约束的话,需先创建主表,再创建从表
 6. 删除表时,先删除从表(或先删除外键约束),再删除从表
 7. 当主表的记录被从表参照时,主表记录将不允许删除,如果要删除数据,需先删除从表中依赖该记录的数据,然后才可以删除主表的数据
 8. 在从表中指定外键约束,并且一个表可以建立多个外键约束
 9. 从表的外键列与主表被参照的列名字可以不相同,但是数据类型必须一样,逻辑意义一致,如果类型不一样,创建了表时会报错
 10.当创建外键约束时,系统默认会在所在列上建立对应的普通索引,但索引名是列名,不是外键的约束名(外键查询效率高)
 11.删除外键约束后,必须手动删除对应的索引 
 #如员工表的员工所在的部门这个字段的值要参考部门表:部门表是主表,员工表是从表
#创建主表dep1    
mysql> create table dep1(dept_id int,dept_name varchar(15));
Query OK, 0 rows affected (0.02 sec)
#因为主表中没有创建主键或唯一键,会报错
mysql> create table emp1(emp_id int primary key auto_increment,emp_name varchar(15),department_id int,constraint fk_emp1_dept_id foreign key(department_id) references dep1(dept_id));
ERROR 1822 (HY000): Failed to add the foreign key constraint. Missing index for constraint 'fk_emp1_dept_id' in the referenced table 'dep1'
#给主表添加主键
mysql> alter table dep1 add primary key(dept_id);
Query OK, 0 rows affected (0.03 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> create table emp1(emp_id int primary key auto_increment,emp_name varchar(15),department_id int,constraint fk_emp1_dept_id foreign key(department_id) references dep1(dept_id));
Query OK, 0 rows affected (0.02 sec)
#查看表约束
mysql> select * from information_schema.table_constraints where table_name='emp1';
+--------------------+-------------------+-----------------+--------------+------------+-----------------+----------+
| CONSTRAINT_CATALOG | CONSTRAINT_SCHEMA | CONSTRAINT_NAME | TABLE_SCHEMA | TABLE_NAME | CONSTRAINT_TYPE | ENFORCED |
+--------------------+-------------------+-----------------+--------------+------------+-----------------+----------+
| def                | dbtest13          | PRIMARY         | dbtest13     | emp1       | PRIMARY KEY     | YES      |
| def                | dbtest13          | fk_emp1_dept_id | dbtest13     | emp1       | FOREIGN KEY     | YES      |
+--------------------+-------------------+-----------------+--------------+------------+-----------------+----------+
2 rows in set (0.00 sec)
#直接更新从表中(外键值在主表中如果不存在,则会报错)
mysql> insert into emp1 values(1001,'Tom',10);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`dbtest13`.`emp1`, CONSTRAINT `fk_emp1_dept_id` FOREIGN KEY (`department_id`) REFERENCES `dep1` (`dept_id`))
#先在主表中添加信息后,然后在从表中添加数据
mysql> insert into dep1 values(10,'IT');
Query OK, 1 row affected (0.00 sec)

mysql> insert into emp1 values(1001,'Tom',10);
Query OK, 1 row affected (0.01 sec)
#主表中删除数据前,需先删除从表中信息
mysql> delete from dep1 where dept_id=10;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`dbtest13`.`emp1`, CONSTRAINT `fk_emp1_dept_id` FOREIGN KEY (`department_id`) REFERENCES `dep1` (`dept_id`))

#约束等级
 - Cascade(级联)方式:在父表update/delete记录时,同步删除从表中的记录
 - Set null方式:在父表上update/delete记录时,将子表中匹配记录的列设为null,但从表的外键不能设定为not null
 - No action方式:如果子表中有匹配的记录,则不允许对父表对应候选键进行update/delete操作
 - Restrict方式:同no action,都是立即检查外键约束
 - Set default方式,父表有变更时,子表将外键设定为一个默认的值,但innodb不能识别
 - 默认等级为Restrict,对于外键约束,最好采用ON UPDATE CASCADE ON DELETE RESTRICT的方式
##在MySQL里,外键约束是有成本的,需要消耗系统资源,对于大并发的SQL操作,可能会因为外键约束的系统开销变得很慢,MySQL允许不使用自带的外键约束,在应用层面完成数据一致性的逻辑。
外键级连适合单机低并发,不适合分布式高并发环境
CHECK约束
CHECK约束:检查某个字段的值是否符合xx要求,一般指取值范围
mysql> create table test10(id int,last_name varchar(20),salary decimal(10,2),check(salary>2000));
Query OK, 0 rows affected (0.03 sec)

mysql> insert into test10 values(10,'tome',2500);
Query OK, 1 row affected (0.00 sec)

mysql> insert into test10 values(10,'tome',1500);
ERROR 3819 (HY000): Check constraint 'test10_chk_1' is violated.

DEFAULT约束
问:为什么建表时,加not null default ''或default 0
不想让表出现null值
问:为什么不想要null值
1. 不好比较,null是一种特殊值,比较时需使用函数 is null 或not is null,使用运算符则返回null
2. 效率不高,影响索引效果
问:带AUTO_INCREMENT约束的字段是从1开始的吗
在MySQL中,默认AUTO_INCREMENT的初使值是1,每新增一条记录,字段值自动加1,设置了AUTO_INCREMENT的时候,可以提前插入一条记录如(自增字段)id=5,则下一条记录则会从6开始
问:并不是每个表都可以任意选择存储引擎
外键约束不能跨引擎使用
MySQL支持多种存储引擎,每一个表可以指定不同的存储引擎,外键约束是保证数据的参照完整性的,如表之间需要关联外键,却指定了不同存储引擎,那么表之间不能创建外键约束,所以存储引擎选择不是随意的。

以上是关于mysql唯一约束的主要内容,如果未能解决你的问题,请参考以下文章

MySQL添加唯一约束和联合唯一约束

mysql中唯一约束、key和索引的区别,unique key 就是唯一约束吗,新手麻烦指点,谢谢

MySQL中的唯一约束

MYSQL中唯一约束和唯一索引的区别

Mysql数据唯一约束与唯一索引案例总结及踩坑记(含NULL值与唯一约束唯一索引的搭配使用)

MySQL约束 主键约束丨唯一约束丨非空约束丨外键级联