mysql对象之约束实践总结一

文章目录

  • 第1章 约束介绍与实践环境
    • 1.1 约束的简介
    • 1.2 实践环境说明
  • 第2章 非空约束(not null)
    • 2.1 非空约束的总结
    • 2.2 非空约束的创建
    • 2.3 字段指定了非空约束
    • 2.4 字段未指定非空约束
    • 2.5 给有空值的字段添加非空约束
  • 第3章 默认约束(default)
    • 3.1 默认约束的总结
    • 3.2 字段为权举数据类型,用default指定了默认值
    • 3.3 字段集合数据类型,用default指定了默认值
    • 3.4 字段日期数据类型,用default指定了默认值
  • 第4章 自增约束(auto_increment)
    • 4.1 自增约束的总结
    • 4.2 自增约束不配合key使用时,创建会失败
    • 4.3 自增约束配合primary key使用
    • 4.4 自增约束配合unique key使用
    • 4.5 指定某一张表的自增字段下一次从某个值开始自增
    • 4.6 自增约束为何是从1开始的,修改了相关参数会怎样
  • 第5章 唯一约束(unique key)
    • 5.1 唯一约束的总结
    • 5.2 唯一约束的几种创建方法
    • 5.3 单列唯一约束的实践(没有not null约束)
    • 5.4 多列唯一约束的实践(没有not null约束)
    • 5.5 在插入数据时怕有重复值应该怎么做
    • 5.6 有重复值的字段如何创建唯一约束
  • 第6章 主键约束(primary key)
    • 6.1 主键约束的总结
    • 6.2 单列主键约束(常用的)
    • 6.3 多列主键约束(不常用)
    • 6.4 我们认为的primary key
    • 6.5 数据库认为primary key
    • 6.6 如何查询某个库中哪些表没有主键索引

第1章 约束介绍与实践环境

1.1 约束的简介

约束的作用是保证数据的正确性和一至性,它是在mysql层面来实现的(它是mysql的功能/对象)。其实数据的正确性和一致是开发人员和DBA人员一起来实现的。约束只是保证数据正确性和一至性的一个方面。约束分为以下几类:

非空约束(not null)         字段级别上指定   
默认约束(default)          字段级别上指定
自增约束(auto_increment)   字段级别上指定
唯一约束(unique key)       字段级别上指定
主键约束(primary key)      字段级别上指定
外键约束(foreign key)      从表/子表的字段级别上指定,此篇博文不会涉及,请看  https://blog.csdn.net/weixin_43733154/article/details/107961396

1.2 实践环境说明

#### 数据库版本和当前MySQL实例默认的存储引擎
mysql> select @@version,@@global.default_storage_engine;
+------------+---------------------------------+
| @@version  | @@global.default_storage_engine |
+------------+---------------------------------+
| 5.7.28-log | InnoDB                          |
+------------+---------------------------------+
1 row in set (0.00 sec)


#### 查看事务在当前会话下和全局下的提交方式是否为自动提交
mysql> select @@global.autocommit,@@autocommit;
+---------------------+--------------+
| @@global.autocommit | @@autocommit |
+---------------------+--------------+
|                   1 |            1 |
+---------------------+--------------+
1 row in set (0.00 sec)


#### 会话模式下和全局模式下的SQL模式(是否包含严格模式STRICT_TRANS_TABLES)
mysql> select @@sql_mode\G
*************************** 1. row ***************************
@@sql_mode: 
STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,
NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
1 row in set (0.00 sec)

mysql> select @@global.sql_mode\G
*************************** 1. row ***************************
@@global.sql_mode: 
STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,
NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
1 row in set (0.00 sec)


#### 创建binbin库,并进入到binbin库下面;
create database if not exists binbin character set utf8 collate utf8_general_ci;
use binbin; 
select database();


第2章 非空约束(not null)

2.1 非空约束的总结

01:是在表的字段级别上进行指定,不用管字段的数据类型是什么;

02:一张表可以有多个字段拥有非空约束,其创建方法如下所示:
	A:第一种:创建表时在相应的字段指定not null
	B:第二种:表创建后用alter table 表名 modify ....; 来修改相关字段的属性;
	C:注意:用第二种方法时,若相关字段的值有空值时则指定不会成功;

03:字段指定了非空约束(not null)
    A:sql_mode开启了严格模式,插入数据时不为字段指定值,会直接报错;
    B:sql_mode未开启严格模式,插入数据时不为字段指定值,不报错,该字段显示空值(不是用null来表示的哈)
    
04:字段未指定非空约束(not null)
    A:此时不管你的sql_mode有没有开启严格模式;
    B:不为字段指定值时,不会报错,默认用空值(是用null来表示的哈)表示;

2.2 非空约束的创建

在创建表时就为相关字段指定非空约束

#### 创建test22_1表
create table if not exists test22_1(
	name varchar(20) not null comment"姓名",   # 为name字段指定了非空约束(not null)
	sex varchar(20) not null comment"性别"     # 为sex字段指定了非空约束(not null)
)engine=innodb character set utf8 collate utf8_general_ci comment"测试表22_1";


#### 查看test22_1表的表结构
mysql> desc test22_1;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| name  | varchar(20) | NO   |     | NULL    |       |
| sex   | varchar(20) | NO   |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

表创建成功后(没有任何数据),给相关字段进行添加

#### 创建test22_2表,在创建表时不为name、sex字段指定非空约束
create table if not exists test22_2(
	name varchar(20) comment"姓名",            # 没有为name字段指定非空约束(not null)
	sex varchar(20) comment"性别"              # 没有为sex字段指定非空约束(not null)
)engine=innodb character set utf8 collate utf8_general_ci comment"测试表22_2";


#### 查看test22_2表的表结构
mysql> desc test22_2;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| name  | varchar(20) | YES  |     | NULL    |       |
| sex   | varchar(20) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)


#### 修改test22_2表中的name字段和sex字段拥有非空约束
mysql> select count(*) from test22_2 where name is null;  # 注意哈:test22_2表中没有任何的数据哈
+----------+
| count(*) |
+----------+
|        0 |
+----------+
1 row in set (0.00 sec)

    ## PS:以下命令在修改test22_2表中name字段和sex字段的属性前,你应该先看一看表(test22_2)的创建语句
    ## show create table test22_2;
    
mysql> alter table test22_2 modify name varchar(20) not null comment"姓名";
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> alter table test22_2 modify sex varchar(20) not null comment"性别";
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc test22_2;   # 查看test22_2表的表结构
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| name  | varchar(20) | NO   |     | NULL    |       |
| sex   | varchar(20) | NO   |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

2.3 字段指定了非空约束

创建表且给相应字段指定非空约束

#### 创建test23表
create table if not exists test23(
  name varchar(20) not null comment"姓名",   # 指定了非空约束(not null)
  sex varchar(20)  not null comment"性别"    # 指定了非空约束(not null)
)engine=innodb character set utf8 collate utf8_general_ci comment"测试表23";


#### 查看test23表的表结构
mysql> desc test23;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| name  | varchar(20) | NO   |     | NULL    |       |
| sex   | varchar(20) | NO   |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec) ^==no表示具备非空约束(not null)

sql_mode中包含严格模式的情况下插入数据

#### 会话模式下SQL_MODE开启了严格模式
set session sql_mode="strict_trans_tables";
select @@sql_mode;


#### 往test23表中插入数据(给name字段指定数据,不给sex字段指定数据)
mysql> insert into test23(name) values("chenliang");
ERROR 1364 (HY000): Field 'sex' doesn't have a default value   <==直接报错

mysql> select * from test23;
Empty set (0.01 sec)

sql_mode中未开启严格模式的情况下插入数据

#### 修改当前会话模式下sql_mode中不包含严格模式
set session sql_mode="";
select @@sql_mode;


#### 往test23表中插入数据(给name字段指定数据,不给sex字段指定数据)
mysql> insert into test23(name) values("chenliang");
Query OK, 1 row affected, 1 warning (0.00 sec)

mysql> select * from test23;
+-----------+-----+
| name      | sex |
+-----------+-----+
| chenliang |     |  <== sex字段是空值(不会用null来表示)
+-----------+-----+
1 row in set (0.00 sec)

#### 查询出test23表中sex为空(不是用null来表示的)的记录
mysql> select * from test23 where sex="";
+-----------+-----+
| name      | sex |
+-----------+-----+
| chenliang |     |
+-----------+-----+
1 row in set (0.00 sec)


#### 将当前会话模式下的sql_mode修改回源样(即包含严格模式)
mysql> set session sql_mode="STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION";
Query OK, 0 rows affected (0.00 sec)

2.4 字段未指定非空约束

创建test24表,相应字段不具备非空约束(not null)

#### 创建test24表
create table if not exists test24(
  name varchar(20) comment"姓名",  # 没有指定非空约束(not null)哈
  sex varchar(20) comment"性别"    # 没有指定非空约束(not null)哈
)engine=innodb character set utf8 collate utf8_general_ci comment"测试表24";


#### 查看test24表的表结构可以看到name字段的属性为非空约束,sex字段没有指定非空约束
mysql> desc test24;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| name  | varchar(20) | YES  |     | NULL    |       |
| sex   | varchar(20) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

往test24表中插入数据(不用管sql_mode有没有开启严格模式)

#### 往test24表中插入数据(给name字段指定数据,不给sex字段指定数据)
mysql> insert into test24(name) values("chenliang");
Query OK, 1 row affected (0.00 sec)

mysql> select * from test24;
+-----------+------+
| name      | sex  |
+-----------+------+
| chenliang | NULL |  <== sex字段是用NULL来表示的是为空值
+-----------+------+
1 row in set (0.00 sec)


#### 查询test24表中sex字段为空(用null来表示的)的记录
mysql> select * from test24 where sex is null;
+-----------+------+
| name      | sex  |
+-----------+------+
| chenliang | NULL |
+-----------+------+
1 row in set (0.00 sec)

2.5 给有空值的字段添加非空约束

#### 创建test25表
create table if not exists test25(
    id int unsigned auto_increment comment"序列",
	name varchar(20) comment"姓名",            # name字段没有指定非空约束哈
	sex varchar(20) not null comment"性别",
	primary key(id)
)engine=innodb character set utf8 collate utf8_general_ci comment"测试表25";


#### 查看test25表的表结构
mysql> desc test25;
+-------+------------------+------+-----+---------+----------------+
| Field | Type             | Null | Key | Default | Extra          |
+-------+------------------+------+-----+---------+----------------+
| id    | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| name  | varchar(20)      | YES  |     | NULL    |                |
| sex   | varchar(20)      | NO   |     | NULL    |                |
+-------+------------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)


#### 插入几条测试数据
-- 正常插入数据
insert into test25(name,sex) values("chenliang01","男");
insert into test25(name,sex) values("chenliang02","男");
insert into test25(name,sex) values("chenliang03","男");

-- 没有往name字段插入数据
insert into test25(sex) values("女");

-- 正常插入数据
insert into test25(name,sex) values("chenliang05","女");
insert into test25(name,sex) values("chenliang06","女");

-- 没有往name字段插入数据
insert into test25(sex) values("男");

-- 正常插入数据
insert into test25(name,sex) values("chenliang08","男");
insert into test25(name,sex) values("chenliang09","男");


#### 查看test25表中的所有数据
mysql> select * from test25;
+----+-------------+-----+
| id | name        | sex |
+----+-------------+-----+
|  1 | chenliang01 ||
|  2 | chenliang02 ||
|  3 | chenliang03 ||
|  4 | NULL        ||  <==name字段有空值
|  5 | chenliang05 ||
|  6 | chenliang06 ||
|  7 | NULL        ||  <==name字段有空值
|  8 | chenliang08 ||
|  9 | chenliang09 ||
+----+-------------+-----+
9 rows in set (0.00 sec)


#### 此时你为name添加非空约束时会报错
mysql> alter table test25 modify name varchar(20) not null comment"姓名";
ERROR 1138 (22004): Invalid use of NULL value


#### 查询出哪些记录中name字段为空值
mysql> select * from test25 where name is null;
+----+------+-----+
| id | name | sex |
+----+------+-----+
|  4 | NULL ||
|  7 | NULL ||
+----+------+-----+
2 rows in set (0.00 sec)

    你可能会想到,如果我修改当前会话下的sql_mode中不包括严格模式,然后就直接alter进行
    为name字段添加非空约束,能不能句成功,答案是可以成功的,当成功后,id等于4和7的记
    录就会变成如下所示:你可以用select * from test25 where name="";来查询出来
	+----+------+-----+
	| id | name | sex |
	+----+------+-----+
	|  4 |      ||
	|  7 |      ||
	+----+------+-----+


#### 用update更新第id等于4和id等于7记录中name字段的值为"null+1",要加条件哈,我这张表的id字段是主键字段的哈
update
  test25
set
  name="null+1"
where
  id in(4,7) and name is null;


mysql> select * from test25 where name is null;
Empty set (0.00 sec)



#### 用alter命令给test25表的name字段添加上非空约束
mysql> show create table test25\G               # 查看test25表的创建语句,用得着
*************************** 1. row ***************************
       Table: test25
Create Table: CREATE TABLE `test25` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '序列',
  `name` varchar(20) DEFAULT NULL COMMENT '姓名',
  `sex` varchar(20) NOT NULL COMMENT '性别',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8 COMMENT='测试表25'
1 row in set (0.00 sec)

mysql> alter table test25 modify name varchar(20) not null COMMENT '姓名';
Query OK, 0 rows affected (0.03 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc test25;
+-------+------------------+------+-----+---------+----------------+
| Field | Type             | Null | Key | Default | Extra          |
+-------+------------------+------+-----+---------+----------------+
| id    | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| name  | varchar(20)      | NO   |     | NULL    |                |  <==name字段已经具有非空约束
| sex   | varchar(20)      | NO   |     | NULL    |                |
+-------+------------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)


第3章 默认约束(default)

3.1 默认约束的总结

01:它是在表的字段级别上进行指定,一张表中允许多个字段拥有默认约束(default);

02:当为字段指定默认约束的值时,需要根据字段的数据类型来指定,默认约束的值必须得是一个确认的值或者是变量(不是函数哈);

03:字段没有指定非空约束(not null),不管字段是啥数据类型,不管sql_mode有没有开启严格模式,插入的时候不给字段指定值,
    默认值为空(用NULL来表示)

3.2 字段为权举数据类型,用default指定了默认值

## 创建test32表
create table if not exists test32(
name varchar(20) not null comment"姓名",
  sex  enum("男","女") default"男" comment"性别"  # 默认值为"男"
)engine=innodb character set utf8 collate utf8_general_ci comment"测试表32";

## 查看test32表的表结构
mysql> desc test32;
+-------+-------------------+------+-----+---------+-------+
| Field | Type              | Null | Key | Default | Extra |
+-------+-------------------+------+-----+---------+-------+
| name  | varchar(20)       | NO   |     | NULL    |       |
| sex   | enum('男','女')   | YES  |     ||       |
+-------+-------------------+------+-----+---------+-------+
2 rows in set (0.01 sec)     <==name字段没有指定非空约束 <==name字段默认值为"男"

## 往test32表中插入数据(给name指定数据,不给sex字段指定数据)
mysql> insert into test32(name) values("chenliang");
Query OK, 1 row affected (0.00 sec)

mysql> select * from test32;
+-----------+------+
| name      | sex  |
+-----------+------+
| chenliang || <== sex字段的值默认就是"男"
+-----------+------+
1 row in set (0.00 sec)

3.3 字段集合数据类型,用default指定了默认值

## 创建test33表
create table if not exists test33(
  name varchar(20) not null comment"姓名",
  vip  set("vip1","vip2","vip3") default"vip1" comment"会员"  # 默认值为"vip1"
)engine=innodb character set utf8 collate utf8_general_ci comment"测试表33";

## 查看test33表的表结构
mysql> desc test33;
+-------+---------------------------+------+-----+---------+-------+
| Field | Type                      | Null | Key | Default | Extra |
+-------+---------------------------+------+-----+---------+-------+
| name  | varchar(20)               | NO   |     | NULL    |       |
| vip   | set('vip1','vip2','vip3') | YES  |     | vip1    |       |
+-------+---------------------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

## 往test33表中插入数据(给name字段指定数据,不给vip字段指定数据)
mysql> insert into test33(name) values("chenliang01");
Query OK, 1 row affected (0.01 sec)

mysql> select * from test33;
+-------------+------+
| name        | vip  |
+-------------+------+
| chenliang01 | vip1 |  <== 没往vip字段插入数据,但vip字段默认值为vip1
+-------------+------+
1 row in set (0.00 sec)

3.4 字段日期数据类型,用default指定了默认值

## 创建test34表
create table if not exists test34(
  name varchar(20) not null comment"姓名",
  t_time datetime default current_timestamp comment"时间" # 默认值是变量current_timestamp
)engine=innodb character set utf8 collate utf8_general_ci comment"测试表34";

## 查看test34表的表结构
mysql> desc test34;
+--------+-------------+------+-----+-------------------+-------+
| Field  | Type        | Null | Key | Default           | Extra |
+--------+-------------+------+-----+-------------------+-------+
| name   | varchar(20) | NO   |     | NULL              |       |
| t_time | datetime    | YES  |     | CURRENT_TIMESTAMP |       |
+--------+-------------+------+-----+-------------------+-------+
2 rows in set (0.00 sec) <==t_time字段没指定非空约束,默认值为current_timestamp变量

## 往test34表中的name字段插入数据,不往t_time字段插入数据,
mysql> insert into test34(name) values("chenliang");
Query OK, 1 row affected (0.00 sec)

mysql> select * from test34;
+-----------+---------------------+
| name      | t_time              |
+-----------+---------------------+
| chenliang | 2020-04-28 09:15:03 | <==t_time的数据以你的系统时间为准的
+-----------+---------------------+
1 row in set (0.00 sec)

第4章 自增约束(auto_increment)

4.1 自增约束的总结

01:是在表的字段级别上进行指定,一张表中只能有一个自增字段;常用于表的"序列"字段中;

02:自增约束(auto_increment)的字段的数据类型必须得为整型,但不是都适合;
    A:整型数据类型有:tinyint、smallint、mediumint、int、integer、bigint
    B:因为auto_increment默认是从1开始自增,所以只需要关注每类整型数据的无符号范围
    C:又因为生产的数据表中可能有很多的数据,若有自增列,则列的数据类型应该为int或bigint整型数据类型
    
03:当字段的数据类型为int或bigint时,auto_increment的最大值是多少呢?
    A:字段数据类型:int unsigned     auto_increment最大值:4294967295(就是int无符号下的最大值)
    B:字段数据类型:bigint unsigned  auto_increment最大值:18446744073709551615(就是bigint无符号下的最大值)
    C:当数据类型为int或bigint时,auto_increment的最大值就是它们的“无符号”范围,不包括0,因为auto_increment是从1开始自增 
    
04:站在自增约束的角度来说:拥有自增约束的字段的值必须得唯一,但自增约束不包含让其唯一性的功能,只有自增的功能,
    所以需要配合key(primary或unique)使用,但我们通常让其配合主键key来使用。若没有配合key使用,会报如下的错误:
	ERROR 1075 (42000): Incorrect table definition; there can be only one auto
	column and it must be defined as a key
	
05:我们也可以指定某一张表的自增字段下一次从哪个值开始自增
    A:当然你要知道当前表的自增字段已经自增到哪了;
    B:用alter进行修改:alter table 表名 auto_increment=整数(大于A步骤得到的值)
    
06:auto_increment为何默认是从1开始自增的;
	auto_increment_offset=1  
	# 表示第一次自增时,从1开始,该参数的值不能大于auto_increment_increment的值
	
	auto_increment_increment=1 
	# 表示第一次自增后,每次自增时步长多少,

	PS1:以上两个参数可在线修改,修改后会对已存在的表(含自增)和新创建的表(含自增)有影响
	
	示例1:在线修改auto_increment_offset=1  auto_increment_increment=2
	01:之前的表(含自增),自增字段目前已经自增到40了
		A:下次自增就应该是41
		B:第二次自增43
		C:第三次自增45
		D:以此类推
		
	02:新创建的表(含自增)
		A:第一次自增是1
		B:第二次自增是3
		C:第三次自增是5
		D:以准类推;

4.2 自增约束不配合key使用时,创建会失败

mysql> create table if not exists test42(
    ->   id int unsigned auto_increment comment"序列",
    ->   name varchar(20) not null comment"姓名"
    -> )engine=innodb character set utf8 collate utf8_general_ci comment"测试表42";
ERROR 1075 (42000): Incorrect table definition; there can be only one auto column
and it must be defined as a key
   ## 报错翻译:表定义不正确;只能有一个自动列,必须将其定义为键
   ## 报错原因:test42表的id字段没有添加key;

4.3 自增约束配合primary key使用

## 创建test43表
create table if not exists test43(
  id int unsigned auto_increment comment"序列",  # 指定了自增约束的哈
  name varchar(20) not null comment"姓名",
  primary key(id)                                # 指定了id字段为主键key
)engine=innodb character set utf8 collate utf8_general_ci comment"测试表43";

## 查看test43表的表结构
mysql> desc test252;
+-------+------------------+------+-----+---------+----------------+
| Field | Type             | Null | Key | Default | Extra          |
+-------+------------------+------+-----+---------+----------------+
| id    | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| name  | varchar(20)      | NO   |     | NULL    |                |
+-------+------------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)

## 站点在索引的角色去看PRI
mysql> show index from test43\G
*************************** 1. row ***************************
        Table: test43
   Non_unique: 0
     Key_name: PRIMARY  <==key名为primary,可以得知是主键key
 Seq_in_index: 1
  Column_name: id
    Collation: A
  Cardinality: 0
     Sub_part: NULL
       Packed: NULL
         Null: 
   Index_type: BTREE
      Comment: 
Index_comment: 
1 row in set (0.00 sec)

## 站在约束的角度去看PRI
select 
	table_schema as "库名",
	table_name as "表名",
	column_name as "字段名",
	constraint_name as "约束名"
from
 information_schema.key_column_usage
where table_schema="binbin" and table_name="test43";

+--------+--------+-----------+-----------+
| 库名   | 表名   | 字段名    | 约束名        |
+--------+--------+-----------+-----------+
| binbin | test43 | id        | PRIMARY   |
+--------+--------+-----------+-----------+
1 row in set (0.00 sec)

## 往test43表中插入两条数据,不指定往id列插入数据
mysql> insert into test43(name) values("chenliang01"),("chenliang02");
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> select * from test43;
+----+-------------+
| id | name        |
+----+-------------+
|  1 | chenliang01 |
|  2 | chenliang02 |
+----+-------------+
2 rows in set (0.00 sec)

## 查看test43表的id字段下一次自增的是到哪个数值
mysql> show table status from binbin where name="test43"\G
*************************** 1. row ***************************
           Name: test43
         Engine: InnoDB
        Version: 10
     Row_format: Dynamic
           Rows: 2
 Avg_row_length: 8192
    Data_length: 16384
Max_data_length: 0
   Index_length: 0
      Data_free: 0
 Auto_increment: 3                <==下一次应该自增到3
    Create_time: 2020-04-28 10:03:42
    Update_time: 2020-04-28 10:07:52
     Check_time: NULL
      Collation: utf8_general_ci
       Checksum: NULL
 Create_options: 
        Comment: 测试表43
1 row in set (0.00 sec)

## 再往43表中插入一条数据,不指定id列,看其是否是自增到3
mysql> insert into test43(name) values("chenliang03");
Query OK, 1 row affected (0.00 sec)

mysql> select * from test43;
+----+-------------+
| id | name        |
+----+-------------+
|  1 | chenliang01 |
|  2 | chenliang02 |
|  3 | chenliang03 |
+----+-------------+
3 rows in set (0.00 sec)

## 其实也可以指定id字段的值,但你指定的值一定是得大于它下次自增的值,但不这样干
mysql> insert into test43(id,name) values(5,"chenliang05");
Query OK, 1 row affected (0.01 sec)

mysql> select * from test43;
+----+-------------+
| id | name        |
+----+-------------+
|  1 | chenliang01 |
|  2 | chenliang02 |
|  3 | chenliang03 |
|  5 | chenliang05 |   <==5是我们指定的,它比3大,所以成功,下一次自增的就该是到6了
+----+-------------+
4 rows in set (0.00 sec)

4.4 自增约束配合unique key使用

## 创建test44表
create table if not exists test44(
  id int unsigned not null auto_increment unique comment"序列", 
  # id字段指定了自增约束和uniquekey的哈
  name varchar(20) not null comment"姓名"
)engine=innodb character set utf8 collate utf8_general_ci comment"测试表44";

## 查看test44表的表结构
mysql> desc test44;
+-------+------------------+------+-----+---------+----------------+
| Field | Type             | Null | Key | Default | Extra          |
+-------+------------------+------+-----+---------+----------------+
| id    | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| name  | varchar(20)      | NO   |     | NULL    |                |
+-------+------------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)            
   
   ## PRI:从mysql角度来说,就是主键,但不是我们用priamry key指定的,因为表中我们没有用primary key指定,但
   ## 我们为id字段指定了not null和auto_increment(自增嘛,肯定不会重复),且因为表是innodb存储引擎,把以
   ## 它会把id字段认为是主键字段;

## 站点在索引的角度去看PRI
mysql> show index from test44\G
*************************** 1. row ***************************
        Table: test44
   Non_unique: 0
     Key_name: id   <==key名为id
 Seq_in_index: 1
  Column_name: id   <==字段名:id
    Collation: A
  Cardinality: 0
     Sub_part: NULL
       Packed: NULL
         Null: 
   Index_type: BTREE
      Comment: 
Index_comment: 
1 row in set (0.00 sec)


## 站在约束的角度看一看PRI
select 
	table_schema as "库名",
	table_name as "表名",
	column_name as "字段名",
	constraint_name as "约束名"
from
 information_schema.key_column_usage
where table_schema="binbin" and table_name="test44";

+--------+--------+-----------+-----------+
| 库名   | 表名   | 字段名    | 约束名    |
+--------+--------+-----------+-----------+
| binbin | test44 | id        | id        |
+--------+--------+-----------+-----------+
1 row in set (0.00 sec)

## 往test44表中插入两条数据,不指定往id列插入数据
mysql> insert into test44(name) values("chenliang01"),("chenliang02");
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> select * from test44;
+----+-------------+
| id | name        |
+----+-------------+
|  1 | chenliang01 |
|  2 | chenliang02 |
+----+-------------+
2 rows in set (0.00 sec)

## 查看test44表id字段下一次自增的是到哪个数值
mysql> show table status from binbin where name="test44"\G
*************************** 1. row ***************************
           Name: test44
         Engine: InnoDB
        Version: 10
     Row_format: Dynamic
           Rows: 2
 Avg_row_length: 8192
    Data_length: 16384
Max_data_length: 0
   Index_length: 0
      Data_free: 0
 Auto_increment: 3   <==下次自增到3
    Create_time: 2020-04-28 10:14:02
    Update_time: 2020-04-28 10:18:58
     Check_time: NULL
      Collation: utf8_general_ci
       Checksum: NULL
 Create_options: 
        Comment: 测试表44
1 row in set (0.00 sec)

## 再往test44表中插入一条数据,不指定id列,看其是否是自增到3
mysql> insert into test44(name) values("chenliang03");
Query OK, 1 row affected (0.00 sec)

mysql> select * from test44;
+----+-------------+
| id | name        |
+----+-------------+
|  1 | chenliang01 |
|  2 | chenliang02 |
|  3 | chenliang03 |
+----+-------------+
3 rows in set (0.00 sec)

## 其实也可以指定id字段的值,但你指定的值一定是得大于它下次自增的值,但不这样干
mysql> insert into test44(id,name) values(5,"chenliang05");
Query OK, 1 row affected (0.00 sec)

mysql> select * from test44;
+----+-------------+
| id | name        |
+----+-------------+
|  1 | chenliang01 |
|  2 | chenliang02 |
|  3 | chenliang03 |
|  5 | chenliang05 |  <==5是我们指定的,它比3大,所以成功,下一次自增的就该是到6了
+----+-------------+
4 rows in set (0.00 sec)

4.5 指定某一张表的自增字段下一次从某个值开始自增

## 创建test45表
create table if not exists test45(
  id bigint unsigned auto_increment comment"序列",    # 指定了自增约束的哈
  name varchar(20) not null comment"姓名",
  primary key(id)                                     # 指定了id字段为主键key
)engine=innodb character set utf8 collate utf8_general_ci comment"测试表45";

## 查看test45表的表结构
mysql> desc test45;
+-------+---------------------+------+-----+---------+----------------+
| Field | Type                | Null | Key | Default | Extra          |
+-------+---------------------+------+-----+---------+----------------+
| id    | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| name  | varchar(20)         | NO   |     | NULL    |                |
+-------+---------------------+------+-----+---------+----------------+
2 rows in set (0.01 sec)

## 往test45表中插入几条测试数据
mysql> insert into test45(name) values("chenliang01"),("chenliang02"),("chenliang03");
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> select * from test45;
+----+-------------+
| id | name        |
+----+-------------+
|  1 | chenliang01 |
|  2 | chenliang02 |
|  3 | chenliang03 |
+----+-------------+
3 rows in set (0.00 sec)

## 查看test45下次自增是到哪
mysql> show table status from binbin where name="test45"\G
*************************** 1. row ***************************
           Name: test45
         Engine: InnoDB
        Version: 10
     Row_format: Dynamic
           Rows: 3
 Avg_row_length: 5461
    Data_length: 16384
Max_data_length: 0
   Index_length: 0
      Data_free: 0
 Auto_increment: 4    <==下次应该自增到4,后面我们让其从40开始自增
    Create_time: 2020-04-28 10:39:12
    Update_time: 2020-04-28 10:41:35
     Check_time: NULL
      Collation: utf8_general_ci
       Checksum: NULL
 Create_options: 
        Comment: 测试表45
1 row in set (0.00 sec)

## 修改test45表的自增字段下次从40开始自增
mysql> alter table test45 auto_increment=40;
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> show table status from binbin where name="test45"\G
*************************** 1. row ***************************
           Name: test45
         Engine: InnoDB
        Version: 10
     Row_format: Dynamic
           Rows: 3
 Avg_row_length: 5461
    Data_length: 16384
Max_data_length: 0
   Index_length: 0
      Data_free: 0
 Auto_increment: 40   <==下次自增字段就应该是从40开始
    Create_time: 2020-04-28 10:45:18
    Update_time: 2020-04-28 10:41:35
     Check_time: NULL
      Collation: utf8_general_ci
       Checksum: NULL
 Create_options: 
        Comment: 测试表45
1 row in set (0.00 sec)

## 往test45表中插入一条数据,不给id字段指定值,看是不是从40开始自增
mysql> select * from test45;
+----+-------------+
| id | name        |
+----+-------------+
|  1 | chenliang01 |
|  2 | chenliang02 |
|  3 | chenliang03 |
+----+-------------+
3 rows in set (0.00 sec)

mysql> insert into test45(name) values("chenliang40");
Query OK, 1 row affected (0.00 sec)

mysql> select * from test45;
+----+-------------+
| id | name        |
+----+-------------+
|  1 | chenliang01 |
|  2 | chenliang02 |
|  3 | chenliang03 |
| 40 | chenliang40 |
+----+-------------+
4 rows in set (0.00 sec)

4.6 自增约束为何是从1开始的,修改了相关参数会怎样

## 创建test46表
create table if not exists test46(
  id bigint unsigned auto_increment comment"序列",   # 指定了自增约束的哈
  name varchar(20) not null comment"姓名",
  primary key(id)                                   # 指定了主键key的哈
)engine=innodb character set utf8 collate utf8_general_ci comment"测试表46";

## 查看test46表的表结构
mysql> desc test46;
+-------+---------------------+------+-----+---------+----------------+
| Field | Type                | Null | Key | Default | Extra          |
+-------+---------------------+------+-----+---------+----------------+
| id    | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| name  | varchar(20)         | NO   |     | NULL    |                |
+-------+---------------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)

## 查看test46表下次从哪个数值开始自增
mysql> show table status from binbin where name="test46"\G
*************************** 1. row ***************************
           Name: test46
         Engine: InnoDB
        Version: 10
     Row_format: Dynamic
           Rows: 0
 Avg_row_length: 0
    Data_length: 16384
Max_data_length: 0
   Index_length: 0
      Data_free: 0
 Auto_increment: 1   <==自增字段下次是从1开始自增的
    Create_time: 2020-04-28 10:50:35
    Update_time: NULL
     Check_time: NULL
      Collation: utf8_general_ci
       Checksum: NULL
 Create_options: 
        Comment: 测试表46
1 row in set (0.00 sec)

## 为什么auto_increment默认是人1开始自增的呢?
mysql> show variables like "auto_in%";
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| auto_increment_increment | 1     |  <==表示第二次自增时,跨1步,也就是2了,以此类推
| auto_increment_offset    | 1     |  <==表示第一次自增默认是从1开始
+--------------------------+-------+
2 rows in set (0.00 sec)

	auto_increment_offset=1
		# 表示auto_increment默认从哪个数值开始自增,默认是从1开始的
		# 可以在线修改,修改后对之前的表(含有自增约束)和新创建的表(含自增)都有影响,
		# 该参数的值不能大于auto_increment_increment的值;
	auto_increment_increment=1
	    # 表示auto_increment自增时的步长(跨几步) 
    
## 修改auto_increment_offset和auto_increment_increment变量后的理论
	auto_increment_offset=1
	auto_increment_increment=2;
	自增就应该是:1,3,5,7,9.......

## 在线修改auto_increment_offset=1和auto_increment_increment=2;
mysql> set session auto_increment_offset=1;
Query OK, 0 rows affected (0.00 sec)

mysql> set session auto_increment_increment=2;
Query OK, 0 rows affected (0.00 sec)

mysql> show variables like "auto_in%";
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| auto_increment_increment | 2     |
| auto_increment_offset    | 1     |
+--------------------------+-------+
2 rows in set (0.01 sec)

## 测试一下之前创建的表46会不会有变化,答案肯定是会有变化的
mysql> select * from test46;
Empty set (0.00 sec)

mysql> show table status from binbin where name="test46"\G
*************************** 1. row ***************************
           Name: test46
         Engine: InnoDB
        Version: 10
     Row_format: Dynamic
           Rows: 0
 Avg_row_length: 0
    Data_length: 16384
Max_data_length: 0
   Index_length: 0
      Data_free: 0
 Auto_increment: 1  <==自增字段下次是从1开始自增的
    Create_time: 2020-04-28 11:22:04
    Update_time: NULL
     Check_time: NULL
      Collation: utf8_general_ci
       Checksum: NULL
 Create_options: 
        Comment: 测试表46
1 row in set (0.00 sec)

mysql> insert into test46(name) values("chenliang01"),("chenliang02");
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> select * from test46;
+----+-------------+
| id | name        |
+----+-------------+
|  1 | chenliang01 |
|  3 | chenliang02 |
+----+-------------+
2 rows in set (0.00 sec)

## 为了后面的实践,我们还是把auto_increment_offset和auto_increment_increment给修改
## 回源来的默认值
set session auto_increment_offset=1;
set session auto_increment_increment=1;

第5章 唯一约束(unique key)

5.1 唯一约束的总结

01:唯一约束其实就是唯一索引,是在表的字段级别上进行指定,一张表中可以有多个唯一约束;

02:仅仅站在唯一约束的角度来说:不能有重复值,但可以有空值(插入数据时不给字段指定值,用NULL来表示)

03:从现实的角度来说:拥有唯一约束的字段就可以允许空值嘛,不一定,得看你有没有在字段上另外加上非空约束。

04:唯一约束在创建时最好为其指定名称,以防止在删除时不小心删除了字段;

05:唯一约束的创建方法如下所示:
    A:建表时在字段上进行指定,这里又有两种方法,如下所示
       a: 例 tel bigint unsigned unique comment"电话"  # 不推荐,约束名是字段名
       b:例 tel bigint unsigned comment"电话",        # 推荐,可以自定义名称
             unique uni_tel(tel)
             
    B:表创建成功后,用alter table 表名 modif.....来修改相关字段的属性,不建议用这种方法,无法进行唯一约束名称的指定
       a:若表中没有任何数据,可以直接用alter命令进行字段的属性更改
       b:若表中相关字段有重复值,你就得先处理,然后再用alter命令进行更改;

    C:表创建成功后,用alter table 表名 add unique.......来添加唯一约束,建议用这种方法,可以自定义唯一约束的名称
       a:若表中没有任何数据,可以直接用alter命令进行字段的属性更改
       b:若表中相关字段有重复值,你就得先处理,然后再用alter命令进行更改;

06:唯一约束可以是在单个字段上进行创建
    A:表中没有主键,你的字段有unique和not null,你用desc看到的是PRI,其实还是唯一约束
    B:表中拥有主键,你的字段有unique和not null,你用desc看到的是UNI,还是唯一约束
    C:表中拥有主键,你的字段有unique,你用desc看到的是UNI,还是唯一约束

07:唯一约束可以把多个字段联合起来进行创建,你用desc看到的是MUI

5.2 唯一约束的几种创建方法

建表时为相应字段指定唯一约束(不指定约束名,默认以字段名为名)

## 创建test52_1表
create table if not exists test52_1(
  id bigint unsigned auto_increment comment"序列",
  name varchar(30) not null comment"姓名",
  tel bigint unsigned unique comment"电话号码",   # 指定了唯一约束,没有not null
  primary key(id)
)engine=innodb character set utf8 collate utf8_general_ci comment"测试表test52_1";

## 查看test52_1表的表结构
mysql> desc test52_1;
+-------+---------------------+------+-----+---------+----------------+
| Field | Type                | Null | Key | Default | Extra          |
+-------+---------------------+------+-----+---------+----------------+
| id    | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| name  | varchar(30)         | NO   |     | NULL    |                |
| tel   | bigint(20) unsigned | YES  | UNI | NULL    |                |
+-------+---------------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)

## 站在索引的角度看一看UNI的名称是什么
mysql> show index from test52_1 where column_name="tel"\G
*************************** 1. row ***************************
        Table: test52_1
   Non_unique: 0
     Key_name: tel    <==key的名称
 Seq_in_index: 1
  Column_name: tel    <==字段名
    Collation: A
  Cardinality: 0
     Sub_part: NULL
       Packed: NULL
         Null: YES
   Index_type: BTREE
      Comment: 
Index_comment: 
1 row in set (0.00 sec)

建表时为相应字段指定唯一约束(给唯一约束指定名称,不让其用字段的名称)

## 创建test52_2表
create table if not exists test52_2(
  id bigint unsigned auto_increment comment"序列",
  name varchar(30) not null comment"姓名",
  tel bigint unsigned comment"电话号码",  # 没有指定not null
  primary key(id),
  unique uni_tel(tel)                     # 指定tel有唯一约束,且命名为uni_tel
)engine=innodb character set utf8 collate utf8_general_ci comment"测试表52_2";

## 查看test52_2表的表结构
mysql> desc test52_2;
+-------+---------------------+------+-----+---------+----------------+
| Field | Type                | Null | Key | Default | Extra          |
+-------+---------------------+------+-----+---------+----------------+
| id    | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| name  | varchar(30)         | NO   |     | NULL    |                |
| tel   | bigint(20) unsigned | YES  | UNI | NULL    |                |
+-------+---------------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)

## 站在索引的角度看一看UNI的名称是什么
mysql> show index from test52_2 where column_name="tel"\G
*************************** 1. row ***************************
        Table: test52_2
   Non_unique: 0
     Key_name: uni_tel   <==key名:uni_tel
 Seq_in_index: 1
  Column_name: tel       <==字段名:tel
    Collation: A
  Cardinality: 0
     Sub_part: NULL
       Packed: NULL
         Null: YES
   Index_type: BTREE
      Comment: 
Index_comment: 
1 row in set (0.00 sec)

建表成功后再为相应的字段指定唯一约束
注意:表没任何数据,用alter table 表名 modify…;来添加

## 创建test52_3表
create table if not exists test52_3(
  id bigint unsigned auto_increment comment"序列",
  name varchar(30) not null comment"姓名",
  tel bigint unsigned comment"电话号码",  # 没有指定唯一约束和not null
  primary key(id)
)engine=innodb character set utf8 collate utf8_general_ci comment"测试表test52_3";

## 查看test52_3表的表结构
mysql> desc test52_3;
+-------+---------------------+------+-----+---------+----------------+
| Field | Type                | Null | Key | Default | Extra          |
+-------+---------------------+------+-----+---------+----------------+
| id    | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| name  | varchar(30)         | NO   |     | NULL    |                |
| tel   | bigint(20) unsigned | YES  |     | NULL    |                |
+-------+---------------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)

## 为test52_3的tel字段添加上唯一约束(注意:表中是没有任何数据的哈)
mysql> show create table test52_3\G          # 查看test52_3表的创建语句,后面有用
*************************** 1. row ***************************
       Table: test52_3
Create Table: CREATE TABLE `test52_3` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '序列',
  `name` varchar(30) NOT NULL COMMENT '姓名',
  `tel` bigint(20) unsigned DEFAULT NULL COMMENT '电话号码',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='测试表test52_3'
1 row in set (0.00 sec)

mysql> alter table test52_3 modify tel bigint(20) unsigned unique COMMENT '电话号码';
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc test52_3;
+-------+---------------------+------+-----+---------+----------------+
| Field | Type                | Null | Key | Default | Extra          |
+-------+---------------------+------+-----+---------+----------------+
| id    | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| name  | varchar(30)         | NO   |     | NULL    |                |
| tel   | bigint(20) unsigned | YES  | UNI | NULL    |                |
+-------+---------------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)                ^==看这

mysql> show index from test52_3 where column_name="tel"\G
*************************** 1. row ***************************
        Table: test52_3
   Non_unique: 0
     Key_name: tel    <==key名:tel
 Seq_in_index: 1
  Column_name: tel    <==列名:tel
    Collation: A
  Cardinality: 0
     Sub_part: NULL
       Packed: NULL
         Null: YES
   Index_type: BTREE
      Comment: 
Index_comment: 
1 row in set (0.00 sec)

建表成功后再为相应的字段指定唯一约束
注意:表没任何数据,用alter table 表名add unique 名称…;来添加

## 创建test52_4表
create table if not exists test52_4(
  id bigint unsigned auto_increment comment"序列",
  name varchar(30) not null comment"姓名",
  tel bigint unsigned comment"电话号码",  # 没有指定唯一约束和not null
  primary key(id)
)engine=innodb character set utf8 collate utf8_general_ci comment"测试表52_4";

## 查看test52_4表的表结构
mysql> desc test52_4;
+-------+---------------------+------+-----+---------+----------------+
| Field | Type                | Null | Key | Default | Extra          |
+-------+---------------------+------+-----+---------+----------------+
| id    | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| name  | varchar(30)         | NO   |     | NULL    |                |
| tel   | bigint(20) unsigned | YES  |     | NULL    |                |
+-------+---------------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)

## 为test52_4表的tel字段添加唯一约束,唯一约束的名称为uni_tel(表中是没有数据的哈)
mysql> alter table test52_4 add unique uni_tel(tel);
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc test52_4;
+-------+---------------------+------+-----+---------+----------------+
| Field | Type                | Null | Key | Default | Extra          |
+-------+---------------------+------+-----+---------+----------------+
| id    | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| name  | varchar(30)         | NO   |     | NULL    |                |
| tel   | bigint(20) unsigned | YES  | UNI | NULL    |                |
+-------+---------------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)                ^==看这

mysql> show index from test52_4 where column_name="tel"\G
*************************** 1. row ***************************
        Table: test52_4
   Non_unique: 0
     Key_name: uni_tel     <== key名:uni_tel
 Seq_in_index: 1
  Column_name: tel         <== 字段名:tel
    Collation: A
  Cardinality: 0
     Sub_part: NULL
       Packed: NULL
         Null: YES
   Index_type: BTREE
      Comment: 
Index_comment: 
1 row in set (0.00 sec)

5.3 单列唯一约束的实践(没有not null约束)

## 创建test53表
create table if not exists test53(
  id bigint unsigned auto_increment comment"序列",
  name varchar(30) not null comment"姓名",
  tel bigint unsigned comment"电话号码",  # 没有指定not null
  primary key(id),
  unique uni_tel(tel)                     # 给tel字段指定了唯一约束,名称为uni_tel
)engine=innodb character set utf8 collate utf8_general_ci comment"测试表53";

## 查看test53表的表结构
mysql> desc test53;
+-------+---------------------+------+-----+---------+----------------+
| Field | Type                | Null | Key | Default | Extra          |
+-------+---------------------+------+-----+---------+----------------+
| id    | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| name  | varchar(30)         | NO   |     | NULL    |                |
| tel   | bigint(20) unsigned | YES  | UNI | NULL    |                |
+-------+---------------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
## 往test53表中插入数据,往tel字段插入重复值,看一看有什么效果
mysql> insert into test53(name,tel) values("chenliang01",18382021111);
Query OK, 1 row affected (0.00 sec)

mysql> insert into test53(name,tel) values("chenliang02",18382022222);
Query OK, 1 row affected (0.00 sec)

mysql> select * from test53;
+----+-------------+-------------+
| id | name        | tel         |
+----+-------------+-------------+
|  1 | chenliang01 | 18382021111 |
|  2 | chenliang02 | 18382022222 |
+----+-------------+-------------+
2 rows in set (0.00 sec)

mysql> insert into test53(name,tel) values("chenliang03",18382022222);
ERROR 1062 (23000): Duplicate entry '18382022222' for key 'uni_tel'
^==报错了,tel字段重复了

## 往test53表中插入数据,不往tel字段插入数据
mysql> select * from test53;
+----+-------------+-------------+
| id | name        | tel         |
+----+-------------+-------------+
|  1 | chenliang01 | 18382021111 |
|  2 | chenliang02 | 18382022222 |
+----+-------------+-------------+
2 rows in set (0.00 sec)

mysql> insert into test53(name) values("chenliang03");
Query OK, 1 row affected (0.00 sec)

mysql> select * from test53;
+----+-------------+-------------+
| id | name        | tel         |
+----+-------------+-------------+
|  1 | chenliang01 | 18382021111 |
|  2 | chenliang02 | 18382022222 |
|  4 | chenliang03 |        NULL | <==NULL表示空值,并不是值是NULL哈
+----+-------------+-------------+
3 rows in set (0.00 sec)

5.4 多列唯一约束的实践(没有not null约束)

## 创建test54表
create table if not exists test54(
  id bigint unsigned auto_increment comment"序列",
  name varchar(30) not null comment"姓名",         # 指定了非空约束
  tel bigint unsigned not null comment"电话号码",  # 指定了非空约束
  primary key(id),
  unique uni_name_tel(name,tel) # 将name和tel字段做联合唯一约束,名称为uni_name_tel
)engine=innodb character set utf8 collate utf8_general_ci comment"测试表54";

## 查看test54表的表结构
mysql> desc test54;
+-------+---------------------+------+-----+---------+----------------+
| Field | Type                | Null | Key | Default | Extra          |
+-------+---------------------+------+-----+---------+----------------+
| id    | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| name  | varchar(30)         | NO   | MUL | NULL    |                |
| tel   | bigint(20) unsigned | NO   |     | NULL    |                |
+-------+---------------------+------+-----+---------+----------------+
3 rows in set (0.01 sec)

## 从索引角度查看test54表中MUL的信息
mysql> show index from test54 where key_name="uni_name_tel"\G
*************************** 1. row ***************************
        Table: test54
   Non_unique: 0               <==0表示唯一约束
     Key_name: uni_name_tel    <==key名:uni_name_tel
 Seq_in_index: 1
  Column_name: name            <==字段名:name
    Collation: A
  Cardinality: 0
     Sub_part: NULL
       Packed: NULL
         Null: 
   Index_type: BTREE
      Comment: 
Index_comment: 
*************************** 2. row ***************************
        Table: test54
   Non_unique: 0             <==0表示唯一约束
     Key_name: uni_name_tel  <==key名:uni_name_tel
 Seq_in_index: 2
  Column_name: tel          <==字段名:tel
    Collation: A
  Cardinality: 0
     Sub_part: NULL
       Packed: NULL
         Null: 
   Index_type: BTREE
      Comment: 
Index_comment: 
2 rows in set (0.00 sec)

## 往test54表中插入数据(让其出现重复值)
mysql> insert into test54(name,tel) values("chenliang01",18382024444);
Query OK, 1 row affected (0.00 sec)

mysql> insert into test54(name,tel) values("chenliang01",18382024444);
ERROR 1062 (23000): Duplicate entry 'chenliang01-18382024444' for key 'uni_name_tel'

mysql> select * from test54;
+----+-------------+-------------+
| id | name        | tel         |
+----+-------------+-------------+
|  1 | chenliang01 | 18382024444 |
+----+-------------+-------------+
1 row in set (0.00 sec)

mysql> insert into test54(name,tel) values("chenliang01",18382025555);
Query OK, 1 row affected (0.00 sec)

mysql> select * from test54;
+----+-------------+-------------+
| id | name        | tel         |
+----+-------------+-------------+
|  1 | chenliang01 | 18382024444 |
|  3 | chenliang01 | 18382025555 |
+----+-------------+-------------+
2 rows in set (0.00 sec)

5.5 在插入数据时怕有重复值应该怎么做

我当前表中有个字段(tel)指定了唯一约束(unique)和非空约束(not ull),当前表中所有记录中的tel字段中没有重复值,但我现在要插入大量的数据(可能有重复值),怎么办?

## 创建test55表
create table if not exists test55(
  id bigint unsigned auto_increment comment"序列",
  name varchar(30) not null comment"姓名",
  tel bigint unsigned not null comment"电话号码",    # 指定了not null约束
  primary key(id), 
  unique uni_tel(tel)                              # 指定了唯一约束,名称为uni_tel
)engine=innodb character set utf8 collate utf8_general_ci comment"测试表55";

## 查看test55表的表结构
mysql> desc test55;
+-------+---------------------+------+-----+---------+----------------+
| Field | Type                | Null | Key | Default | Extra          |
+-------+---------------------+------+-----+---------+----------------+
| id    | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| name  | varchar(30)         | NO   |     | NULL    |                |
| tel   | bigint(20) unsigned | NO   | UNI | NULL    |                |
+-------+---------------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)

## 插入几条测试数据(tel字段没有重复值,所以都能成功)
insert into test55(name,tel) values
("chenliang01",18382024221),("chenliang02",18382024222),
("chenliang03",18382024223),("chenliang04",18382024224);

## 查看test55表中的所有数据(可以看出tel字段没有重复数据)
mysql> select * from test55;
+----+-------------+-------------+
| id | name        | tel         |
+----+-------------+-------------+
|  1 | chenliang01 | 18382024221 |
|  2 | chenliang02 | 18382024222 |
|  3 | chenliang03 | 18382024223 |
|  4 | chenliang04 | 18382024224 |
+----+-------------+-------------+
4 rows in set (0.00 sec)

ignore(忽略重复值,不影响后面的数据插入)

## 查看test55表中的所有数据
mysql> select * from test55;
+----+-------------+-------------+
| id | name        | tel         |
+----+-------------+-------------+
|  1 | chenliang01 | 18382024221 |
|  2 | chenliang02 | 18382024222 |
|  3 | chenliang03 | 18382024223 |
|  4 | chenliang04 | 18382024224 |
+----+-------------+-------------+
4 rows in set (0.00 sec)

## 我现在准备插入数据(注意:tel字段有重复值)
insert into test55(name,tel) values
("chenliang05",18382024223),
("chenliang06",18382024224),
("chenliang07",18382024226);    
# ^==这条语句插入时,肯定会报错,没有任何一条数据到表中,这里不要执行它;

insert ignore into test55(name,tel) values
("chenliang05",18382024223),
("chenliang06",18382024224),
("chenliang07",18382024226);  
 # ^==这条语句执行时不会报错,但有警告,到表中的数据只有("chenliang07",18382024226);

mysql> select * from test55;
+----+-------------+-------------+
| id | name        | tel         |
+----+-------------+-------------+
|  1 | chenliang01 | 18382024221 |
|  2 | chenliang02 | 18382024222 |
|  3 | chenliang03 | 18382024223 |
|  4 | chenliang04 | 18382024224 |
|  5 | chenliang07 | 18382024226 |
+----+-------------+-------------+
5 rows in set (0.00 sec)

replace(先删除重复字段所在的记录,然后用新数据进行替换)

## 查看test55表中的所有数据(tel字段没有重复数据哈)
mysql> select * from test55;
+----+-------------+-------------+
| id | name        | tel         |
+----+-------------+-------------+
|  1 | chenliang01 | 18382024221 |
|  2 | chenliang02 | 18382024222 |
|  3 | chenliang03 | 18382024223 |
|  4 | chenliang04 | 18382024224 |
|  5 | chenliang07 | 18382024226 |
+----+-------------+-------------+
5 rows in set (0.00 sec)

## 我现在准备插入数据(注意:tel字段有重复值)
insert into test55(name,tel) values
("chenliang08",18382024224),
("chenliang09",18382024226),
("chenliang10",18382024230);    
# ^==这条语句插入时,肯定会报错,没有任何一条数据到表中,这里不要执行它;

replace into test55(name,tel) values
("chenliang08",18382024224),
("chenliang09",18382024226),
("chenliang10",18382024230);    
# ^==这条语句执行时不会报错,但有警告,
# 先把tel等于18382024224的记录删除掉,再把("chenliang08",18382024224)拿去替换
# 先把tel等于18382024226的记录删除掉,再把(”chenliang09",18382024226)拿去替换
# 最后插入("chenliang10",18382024230)数据;

mysql> select * from test55;
+----+-------------+-------------+
| id | name        | tel         |
+----+-------------+-------------+
|  1 | chenliang01 | 18382024221 |
|  2 | chenliang02 | 18382024222 |
|  3 | chenliang03 | 18382024223 |
|  8 | chenliang08 | 18382024224 |
|  9 | chenliang09 | 18382024226 |
| 10 | chenliang10 | 18382024230 |
+----+-------------+-------------+
6 rows in set (0.00 sec)

5.6 有重复值的字段如何创建唯一约束

我当前表中的tel字段只指定了非空约束(not null),没有指定唯一约束(unique),现在tel字段中已经有重复的数据了,我现在在tel字段添加唯一约束(肯定失败),那么如何处理呢?

场景模拟

## 创建test56表
create table if not exists test56(
  id bigint unsigned auto_increment comment"序列",
  name varchar(30) not null comment"姓名",
  tel bigint unsigned not null comment"电话号码",  # 指定了非空约束,未指定唯一约束
  primary key(id)
)engine=innodb character set utf8 collate utf8_general_ci comment"测试表56";

## 查看test56表的表结构
mysql> desc test56;
+-------+---------------------+------+-----+---------+----------------+
| Field | Type                | Null | Key | Default | Extra          |
+-------+---------------------+------+-----+---------+----------------+
| id    | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| name  | varchar(30)         | NO   |     | NULL    |                |
| tel   | bigint(20) unsigned | NO   |     | NULL    |                |
+-------+---------------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)

## 往test56表中插入数据(让tel字段的数据重复,会成功,因为tel没有唯一约束)
insert into test56(name,tel) values("chenliang01",18382024221);
insert into test56(name,tel) values("chenliang02",18382024222);
insert into test56(name,tel) values("chenliang03",18382024221);
insert into test56(name,tel) values("chenliang04",18382024224);

## 查看test56表中的所有数据
mysql> select * from test56;
+----+-------------+-------------+
| id | name        | tel         |
+----+-------------+-------------+
|  1 | chenliang01 | 18382024221 |
|  2 | chenliang02 | 18382024222 |
|  3 | chenliang03 | 18382024221 |
|  4 | chenliang04 | 18382024224 |
+----+-------------+-------------+
4 rows in set (0.00 sec)
## 为test56表中的tel字段指定唯一约束
mysql> alter table test56 add unique uni_tel(tel);
ERROR 1062 (23000): Duplicate entry '18382024221' for key 'uni_tel'
^==提示有重复值18382024221

解决思路

## 第一阶段的思路和的操作命令:
	-- 思路
	A:创建一个新表(test56_new),以test56表为准(要它的索引,不要数据)
	B:在新表(teset56_new)中对tel字段添加唯一约束
	
	-- 操作的命令
	use binbin;
	create table if not exists test56_new like test56;
	desc test56_new;
	alter table test56_new add unique uni_tel(tel);
	desc test56_new;

## 第二阶段的思路的操作命令
	-- 思路
	A:对test56表加读锁, 
	B:统计出表总共有少行, select count(*) from test56;
	C:重复的有多少行;     
	B:导出test56表中的数据,并进行修改
	a:insert into修改成insert ignore into
	b:表名修改成test56_new
	C:将B步骤处理的数据,导入到test56_new表中
	
	-- 命令
	use binbin;
	lock table test56 read;
	导出数据和修改,这里你不列出来了,你可以用mysqldump和sqlyog或者navicat工具
	导入数据这里也不列出来了,后面看实践

## 第三阶段的思路和操作命令
-- 思路
A:对test56表进行解锁,并重命名为test56_old;
B:对test56_new表进行重命名为test56;
-- 命令
use binbin;
unlock tables;
rename table test56 to test56_old;
rename table test56_new to test56;

解决思路实践

## 第一阶段:
mysql> create table if not exists test56_new like test56;
Query OK, 0 rows affected (0.00 sec)

mysql> desc test56_new;
+-------+---------------------+------+-----+---------+----------------+
| Field | Type                | Null | Key | Default | Extra          |
+-------+---------------------+------+-----+---------+----------------+
| id    | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| name  | varchar(30)         | NO   |     | NULL    |                |
| tel   | bigint(20) unsigned | NO   |     | NULL    |                |
+-------+---------------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)

mysql> alter table test56_new add unique uni_tel(tel);
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc test56_new;
+-------+---------------------+------+-----+---------+----------------+
| Field | Type                | Null | Key | Default | Extra          |
+-------+---------------------+------+-----+---------+----------------+
| id    | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| name  | varchar(30)         | NO   |     | NULL    |                |
| tel   | bigint(20) unsigned | NO   | UNI | NULL    |                |
+-------+---------------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)

## 第二阶段:
-- 对test56表加读锁,不让其往里面写入数据了
mysql> lock tables test56 read;
Query OK, 0 rows affected (0.00 sec)

## 第三阶段:
use binbin;
unlock tables;
rename table test56 to test56_old;
rename table test56_new to test56;

mysql> select * from test56;
+----+-------------+-------------+
| id | name        | tel         |
+----+-------------+-------------+
|  1 | chenliang01 | 18382024221 |
|  2 | chenliang02 | 18382024222 |
|  4 | chenliang04 | 18382024224 |
+----+-------------+-------------+
3 rows in set (0.00 sec)

mysql> desc test56;
+-------+---------------------+------+-----+---------+----------------+
| Field | Type                | Null | Key | Default | Extra          |
+-------+---------------------+------+-----+---------+----------------+
| id    | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| name  | varchar(30)         | NO   |     | NULL    |                |
| tel   | bigint(20) unsigned | NO   | UNI | NULL    |                |
+-------+---------------------+------+-----+---------+----------------+
3 rows in set (0.01 sec)

第6章 主键约束(primary key)

6.1 主键约束的总结

01:主键约束实践就是主键索引,它是在表的字段级别上进行指定,一张表中只能有一个主键约束/索引

02:主键约束:包含不能重复、不能有空值,相当于unique和not null,生产中应该让其每张表都有一个主键字段,这样可以保证表中的记
    录不重复,至于字段的值能不能够重复,根据你的业务需要进行相关的约束

03:主键约束:不能人为的进行命名,都是由mysql自行命名,名称为PRIMARY

04:可以是单列主键(常用),也可以是联合(多个字段)主键(不常用)

05:你用desc看到的PRI并不是你认为的primary key;有可能是表中没有primary key,但字段拥有unique和not null约束,
    mysql就把它当前了主键字段

6.2 单列主键约束(常用的)

我现在有一张表,我打算让其有一个自增(auto_increment)列(id),且我想让其用为主键字段。主键约束若配合自增(auto_increment)使用时,那么主键只能在一个字段上进行创建。

## 创建test62表
create table if not exists test62(
  id bigint unsigned auto_increment comment"序列",   # 指定了自增
  name varchar(30) not null comment"姓名",
  primary key(id)                                 # 指定了id字段为主键key
)engine=innodb character set utf8 collate utf8_general_ci comment"测试表62";

## 查看test62表的表结构
mysql> desc test62;
+-------+---------------------+------+-----+---------+----------------+
| Field | Type                | Null | Key | Default | Extra          |
+-------+---------------------+------+-----+---------+----------------+
| id    | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| name  | varchar(30)         | NO   |     | NULL    |                |
+-------+---------------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)

## 站在索引的角色看PRI
mysql> show index from test62 where column_name="id"\G
*************************** 1. row ***************************
        Table: test62
   Non_unique: 0
     Key_name: PRIMARY          <== key名:primary
 Seq_in_index: 1
  Column_name: id               <== 字段名:id
    Collation: A
  Cardinality: 0
     Sub_part: NULL
       Packed: NULL
         Null: 
   Index_type: BTREE
      Comment: 
Index_comment: 
1 row in set (0.00 sec)

## 站在约束的角度看PRI
mysql> select * from information_schema.table_constraints where table_schema="binbin" and table_name="test62"\G
*************************** 1. row ***************************
CONSTRAINT_CATALOG: def
 CONSTRAINT_SCHEMA: binbin
   CONSTRAINT_NAME: PRIMARY
      TABLE_SCHEMA: binbin
        TABLE_NAME: test62
   CONSTRAINT_TYPE: PRIMARY KEY
1 row in set (0.00 sec)

## 往test62表中插入数据(不让id字段重复,它是自增的,就不指定它了)
mysql> insert into test62(name) values("chenliang01"),("chenliang02");
Query OK, 2 rows affected (0.01 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> select * from test62;
+----+-------------+
| id | name        |
+----+-------------+
|  1 | chenliang01 |
|  2 | chenliang02 |
+----+-------------+
2 rows in set (0.00 sec)

## 往test62表中插入数据(id字段的值每现在表中的冲突,看一看效果)
mysql> insert insert test62(id,name) values(2,"chenliang03");
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that 
corresponds to your MySQL server version for the right syntax to use near 'insert 
test62(id,name) values(2,"chenliang03")' at line 1

mysql> select * from test62;
+----+-------------+
| id | name        |
+----+-------------+
|  1 | chenliang01 |
|  2 | chenliang02 |
+----+-------------+
2 rows in set (0.00 sec)

6.3 多列主键约束(不常用)

## 创建test63表
create table if not exists test63(
  ip char(15) comment"IP地址",
  port int unsigned comment"端口",
  primary key(ip,port)       # 指定了ip和port字段为主键约束
)engine=innodb character set utf8 collate utf8_general_ci comment"测试表63";
# 其实像这种情况,我们不要用primary key,我们可以对ip和port字段用unique和not
# null来进行约束

## 查看test63表的表结构
mysql> desc test63;
+-------+------------------+------+-----+---------+-------+
| Field | Type             | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+-------+
| ip    | char(15)         | NO   | PRI | NULL    |       |
| port  | int(10) unsigned | NO   | PRI | NULL    |       |
+-------+------------------+------+-----+---------+-------+
2 rows in set (0.00 sec)            
# 你一个怎么有两个主键,不是说一个表只能有一个主键约束的嘛,其实它们是联合主键

## 从主键索引的角度看一年PRI
mysql> show index from test63\G
*************************** 1. row ***************************
        Table: test63
   Non_unique: 0
     Key_name: PRIMARY
 Seq_in_index: 1
  Column_name: ip
    Collation: A
  Cardinality: 0
     Sub_part: NULL
       Packed: NULL
         Null: 
   Index_type: BTREE
      Comment: 
Index_comment: 
*************************** 2. row ***************************
        Table: test63
   Non_unique: 0
     Key_name: PRIMARY
 Seq_in_index: 2
  Column_name: port
    Collation: A
  Cardinality: 0
     Sub_part: NULL
       Packed: NULL
         Null: 
   Index_type: BTREE
      Comment: 
Index_comment: 
2 rows in set (0.00 sec)

## 往表中插入数据(不能重复,不能为空的哈)
mysql> insert into test63(ip,port) values
    -> ("172.16.1.20",80),
    -> ("172.16.1.20",81);
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> select * from test63;
+-------------+------+
| ip          | port |
+-------------+------+
| 172.16.1.20 |   80 |
| 172.16.1.20 |   81 |
+-------------+------+
2 rows in set (0.00 sec)

## 往表中插入数据(我们模拟数据让其重复,肯定是要报错的)
mysql> insert into test63(ip,port) values
    -> ("172.16.1.20",80),
    -> ("172.16.1.30",90);
ERROR 1062 (23000): Duplicate entry '172.16.1.20-80' for key 'PRIMARY'

mysql> select * from test63;
+-------------+------+
| ip          | port |
+-------------+------+
| 172.16.1.20 |   80 |
| 172.16.1.20 |   81 |
+-------------+------+
2 rows in set (0.00 sec)

6.4 我们认为的primary key

我们认为的主键约束就是在字段上使用primary key关键字来进行指定。

## 创建test64表
create table if not exists test64(
  id bigint unsigned auto_increment comment"序列",
  name varchar(30) not null comment"姓名",
  primary key(id)        # 我这里指定了id字段为主键约束的哈
)engine=innodb character set utf8 collate utf8_general_ci comment"测试表64";

## 查看test64表
mysql> desc test64;
+-------+---------------------+------+-----+---------+----------------+
| Field | Type                | Null | Key | Default | Extra          |
+-------+---------------------+------+-----+---------+----------------+
| id    | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| name  | varchar(30)         | NO   |     | NULL    |                |
+-------+---------------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)              ^=不要被它骗了,它有可能不是我们认为的primary 

## 从索引的角度看PRI
mysql> show index from test64\G
*************************** 1. row ***************************
        Table: test64
   Non_unique: 0
     Key_name: PRIMARY   <==看到它就可以认为是我们认为的primary key了
 Seq_in_index: 1
  Column_name: id        <==字段名
    Collation: A
  Cardinality: 0
     Sub_part: NULL
       Packed: NULL
         Null: 
   Index_type: BTREE
      Comment: 
Index_comment: 
1 row in set (0.00 sec)

## 从约束角度看一个
mysql> select * from information_schema.table_constraints where table_schema="binbin" and table_name="test64"\G
*************************** 1. row ***************************
CONSTRAINT_CATALOG: def
 CONSTRAINT_SCHEMA: binbin
   CONSTRAINT_NAME: PRIMARY
      TABLE_SCHEMA: binbin
        TABLE_NAME: test64
   CONSTRAINT_TYPE: PRIMARY KEY
1 row in set (0.00 sec)

6.5 数据库认为primary key

## 创建test65表
create table if not exists test65(
  id bigint unsigned not null unique comment"编号",  # 我指定了not null和unique
  name varchar(30) not null comment"姓名"
)engine=innodb character set utf8 collate utf8_general_ci comment"测试表65";

## 查看test65表的表结构
mysql> desc test65;
+-------+---------------------+------+-----+---------+-------+
| Field | Type                | Null | Key | Default | Extra |
+-------+---------------------+------+-----+---------+-------+
| id    | bigint(20) unsigned | NO   | PRI | NULL    |       |
| name  | varchar(30)         | NO   |     | NULL    |       |
+-------+---------------------+------+-----+---------+-------+
2 rows in set (0.00 sec)               ^==不要认为是用primary key指定一的哈

## 从索引角度看PRI
mysql> show index from test65\G
*************************** 1. row ***************************
        Table: test65
   Non_unique: 0
     Key_name: id   <==key名不是primary就不是用primary key指定的
 Seq_in_index: 1
  Column_name: id   <==字段名
    Collation: A
  Cardinality: 0
     Sub_part: NULL
       Packed: NULL
         Null: 
   Index_type: BTREE
      Comment: 
Index_comment: 
1 row in set (0.00 sec)

## 从约束的角度看一看PRI
mysql> select * from information_schema.table_constraints where table_schema="binbin" and table_name="test65"\G
*************************** 1. row ***************************
CONSTRAINT_CATALOG: def
 CONSTRAINT_SCHEMA: binbin
   CONSTRAINT_NAME: id
      TABLE_SCHEMA: binbin
        TABLE_NAME: test65
   CONSTRAINT_TYPE: UNIQUE
1 row in set (0.00 sec)

6.6 如何查询某个库中哪些表没有主键索引

查询某个库下哪些表有主键(PRI),不管是我们用primary key创建的,还是mysql自先的(表中没有primary key指定,但某个字段非空且唯一。
查询某个库下哪些表没有主键(PRI);

## 查询binbin库下哪些表包含主键(PRI)
select
	table_schema as "库名",
	table_name as "表名"
from
	information_schema.tables
where 
	table_schema="binbin" and table_name in(
		select
			table_name as "表名"
		from 
			information_schema.columns 
		where 
			table_schema="binbin" and column_key="PRI"
	);

## 查询binbin库下哪些表不包含主键(PRI)
select
	table_schema as "库名",
	table_name as "表名"
from
	information_schema.tables
where 
	table_schema="binbin" and table_name not in(
		select
			table_name as "表名"
		from 
			information_schema.columns 
		where 
			table_schema="binbin" and column_key="PRI"
	);

你可能感兴趣的:(#,mysql,5.7.X)