所谓的主键约束就是在数据表中(一般是id字段),选择一个字段充当索引角色。强烈建议一个表中至少要有一个主键索引约束。下面我们介绍主键索引:主键是一个字段的类型,不能够单独的存在。
主键:唯一标识一条记录,主键有约束性(也就是非空和唯一)
mysql> -- 创建一个具有主键索引的数据表 mysql> create table if not exists pm1( -> id int primary key, -> name varchar(20) -> ); Query OK, 0 rows affected (0.01 sec) mysql> show create table pm1\G *************************** 1. row *************************** Table: pm1 Create Table: CREATE TABLE `pm1` ( `id` int(11) NOT NULL, `name` varchar(20) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 1 row in set (0.00 sec) mysql> desc pm1; +-------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+-------+ | id | int(11) | NO | PRI | NULL | | | name | varchar(20) | YES | | NULL | | +-------+-------------+------+-----+---------+-------+ 2 rows in set (0.00 sec) #插入数据 mysql> insert into pm1(id,name) values (1,'张三'),(2,'李 四'); Query OK, 2 rows affected (0.00 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql> select * from pm1; +----+--------+ | id | name | +----+--------+ | 1 | 张三 | | 2 | 李四 | +----+--------+ 2 rows in set (0.00 sec) #重复插入数据提示id被标记主键 mysql> insert into pm1(id,name) values (1,'张三'),(2,'李 四'); ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY' #说明一旦字段被标记成立主键,则其值是无法重复的。除此之外,主键算是MySQL中最快的索引之一
在日常使用数据库的时候常常不知道当天数据的主键索引的编号属于哪一个,这个时候我们就很需要一个自动为我们填充主键编号的功能即为:自增长。
mysql> create table pm2( -> id int primary key auto_increment, -> name varchar(20) -> ); Query OK, 0 rows affected (0.00 sec) mysql> show create table pm2\G *************************** 1. row *************************** Table: pm2 Create Table: CREATE TABLE `pm2` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(20) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 1 row in set (0.00 sec) mysql> desc pm2; +-------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | name | varchar(20) | YES | | NULL | | +-------+-------------+------+-----+---------+----------------+ 2 rows in set (0.01 sec) #插入数据不增加id mysql> insert into pm2(name) values ('张三'),('李四'); Query OK, 2 rows affected (0.00 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql> select * from pm2; +----+--------+ | id | name | +----+--------+ | 1 | 张三 | | 2 | 李四 | +----+--------+ 2 rows in set (0.00 sec) #设置自增长的起始值 mysql> create table pm3( -> id int primary key auto_increment, -> name varchar(20) -> ) engine=innodb auto_increment=100; Query OK, 0 rows affected (0.00 sec) mysql> desc pm3; +-------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | name | varchar(20) | YES | | NULL | | +-------+-------------+------+-----+---------+----------------+ 2 rows in set (0.00 sec) mysql> insert into pm3 (name) values ('张三'),('李四'); Query OK, 2 rows affected (0.00 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql> select * from pm3; +-----+--------+ | id | name | +-----+--------+ | 100 | 张三 | | 101 | 李四 | +-----+--------+ 2 rows in set (0.00 sec)
#当数据表已存在时,为该表添加主键 -- 格式: ALTER TABLE <数据表> ADD PRIMARY KEY(字段名称); mysql> -- 创建表 mysql> create table pm4( -> id int, -> name varchar(20) -> ); Query OK, 0 rows affected (0.01 sec) mysql> desc pm4; +-------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+-------+ | id | int(11) | YES | | NULL | | | name | varchar(20) | YES | | NULL | | +-------+-------------+------+-----+---------+-------+ 2 rows in set (0.00 sec) mysql> -- 添加主键 mysql> alter table pm4 add primary key(id); Query OK, 0 rows affected (0.11 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> desc pm4; +-------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+-------+ | id | int(11) | NO | PRI | NULL | | | name | varchar(20) | YES | | NULL | | +-------+-------------+------+-----+---------+-------+ 2 rows in set (0.00 sec)
#当数据表不需要主键时,可以将其删除 -- 格式: ALTER TABLE <数据表名> DROP PRIMARY KEY; mysql> desc pm4; +-------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+-------+ | id | int(11) | NO | PRI | NULL | | | name | varchar(20) | YES | | NULL | | +-------+-------------+------+-----+---------+-------+ 2 rows in set (0.00 sec) mysql> alter table pm4 drop primary key; Query OK, 0 rows affected (0.13 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> desc pm4; +-------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+-------+ | id | int(11) | NO | | NULL | | | name | varchar(20) | YES | | NULL | | +-------+-------------+------+-----+---------+-------+ 2 rows in set (0.00 sec)
#唯一索引约束跟主键索引类似,也是要求不允许重复,但是主键索引一般作用于id, 唯一索引可以作用于所有的字段。同理唯一索引也是依赖于字段,能够单独存在,可以提高查询效率 #案例: mysql> create table pm5( -> id int primary key auto_increment, -> name varchar(20) unique key -> ) engine=innodb; Query OK, 0 rows affected (0.01 sec) mysql> desc pm5; +-------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | name | varchar(20) | YES | UNI | NULL | | +-------+-------------+------+-----+---------+----------------+ 2 rows in set (0.01 sec) mysql> insert into pm5(name) values ('张三'); Query OK, 1 row affected (0.00 sec) #字段一旦加上了唯一索引,则不能够重复。 mysql> insert into pm5(name) values ('张三'); ERROR 1062 (23000): Duplicate entry '张三' for key 'name'
#通过设置范围,来管控数据。 #案例: mysql> create table pm6( -> id int primary key auto_increment, -> name varchar(20), -> age tinyint(2) check(code >100 and code <200) -> ) engine=innodb; Query OK, 0 rows affected (0.23 sec) mysql> show create table pm6\G *************************** 1. row *************************** Table: pm6 Create Table: CREATE TABLE `pm6` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(20) DEFAULT NULL, `age` tinyint(2) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 1 row in set (0.00 sec) mysql> insert into pm6(name,age) values ('张三',20); Query OK, 1 row affected (0.00 sec) mysql> select * from pm6; +----+--------+------+ | id | name | age | +----+--------+------+ | 1 | 张三 | 20 | +----+--------+------+ 1 row in set (0.00 sec)
#索引创建完成后,可以利用 SQL 语句查看已经存在的索引 -- 查看索引的语法格式如下: SHOW INDEX FROM <表名> [ FROM <数据库名>] #语法说明如下: -- <表名>:指定需要查看索引的数据表名。 -- <数据库名>:指定需要查看索引的数据表所在的数据库,可省略。比如,SHOW INDEX FROM student FROM test; 语句表示查看 test 数据库中 student 数据表的索引。 -- 示例: mysql> show index from pm6\G *************************** 1. row *************************** Table: pm6 Non_unique: 0 Key_name: PRIMARY Seq_in_index: 1 Column_name: id Collation: A Cardinality: 1 Sub_part: NULL Packed: NULL Null: Index_type: BTREE Comment: Index_comment: 1 row in set (0.00 sec)
其中各主要参数说明如下:
参数 | 说明 |
---|---|
Table | 表示创建索引的数据表名,这里是 pm6 数据表。 |
Non_unique | 表示该索引是否是唯一索引。若不是唯一索引,则该列的值为 1;若是唯一索引,则该列的值为 0。 |
Key_name | 表示索引的名称。 |
Seq_in_index | 表示该列在索引中的位置,如果索引是单列的,则该列的值为 1;如果索引是组合索引,则该列的值为每列在索引定义中的顺序。 |
Column_name | 表示定义索引的列字段。 |
Collation | 表示列以何种顺序存储在索引中。在 MySQL 中,升序显示值“A”(升序),若显示为 NULL,则表示无分类。 |
Cardinality | 索引中唯一值数目的估计值。基数根据被存储为整数的统计数据计数,所以即使对于小型表,该值也没有必要是精确的。基数越大,当进行联合时,MySQL 使用该索引的机会就越大。 |
Sub_part | 表示列中被编入索引的字符的数量。若列只是部分被编入索引,则该列的值为被编入索引的字符的数目;若整列被编入索引,则该列的值为 NULL。 |
Packed | 指示关键字如何被压缩。若没有被压缩,值为 NULL。 |
Null | 用于显示索引列中是否包含 NULL。若列含有 NULL,该列的值为 YES。若没有,则该列的值为 NO。 |
Index_type | 显示索引使用的类型和方法(BTREE、FULLTEXT、HASH、RTREE)。 |
Comment | 显示评注。 |
#案例: mysql> create table city( -> id int primary key auto_increment, -> name varchar(20) -> ); Query OK, 0 rows affected (0.01 sec) mysql> create table city2( -> id int primary key auto_increment, -> name varchar(20), -> fid int, -> FOREIGN KEY(fid) REFERENCES city(id) -> ); Query OK, 0 rows affected (0.00 sec) mysql> desc city; +-------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | name | varchar(20) | YES | | NULL | | +-------+-------------+------+-----+---------+----------------+ 2 rows in set (0.00 sec) mysql> desc city2; +-------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | name | varchar(20) | YES | | NULL | | | fid | int(11) | YES | MUL | NULL | | +-------+-------------+------+-----+---------+----------------+ 3 rows in set (0.00 sec) mysql> INSERT INTO city2 (name,fid) VALUES ("青浦区", 1); ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`linux13`.`city2`, CONSTRAINT `city2_ibfk_1` FOREIGN KEY (`fid`) REFERENCES `city` (`id`)) mysql> INSERT INTO city (name) VALUES ("上海市"); Query OK, 1 row affected (0.00 sec) mysql> INSERT INTO city2 (name,fid) VALUES ("青浦区", 1); Query OK, 1 row affected (0.00 sec) mysql> SELECT * FROM city; +----+-----------+ | id | name | +----+-----------+ | 1 | 上海市 | +----+-----------+ 1 row in set (0.00 sec) mysql> SELECT * FROM city2; +----+-----------+------+ | id | name | fid | +----+-----------+------+ | 2 | 青浦区 | 1 | +----+-----------+------+ 1 row in set (0.00 sec) #city2变依赖于city变数据,当city表中没有相关数据时,则不能够添加数据到city2。