首页 > 技术文章 > MySQL主键约束

eisenshu 2021-12-09 17:32 原文

主键不能为空(NULL)、不能重复!!

唯一约束不能重复,但可以为空。

 

1.单主键约束 primary key

mysql> create table user1(
    -> id int primary key,
    -> name varchar(20)
    -> );
Query OK, 0 rows affected (0.01 sec)

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

由于id是主键,因此插入的数据不能有相同的id:

mysql> insert into user1 values(1,'张三');
Query OK, 1 row affected (0.00 sec)

mysql> insert into user1 values(1,'李四');
ERROR 1062 (23000): Duplicate entry '1' for key 'user1.PRIMARY'

但非主键相同可以:

mysql> insert into user1 values(2,'张三');
Query OK, 1 row affected (0.00 sec)

mysql> select *from user1;
+----+--------+
| id | name   |
+----+--------+
|  1 | 张三   |
|  2 | 张三   |
+----+--------+
2 rows in set (0.00 sec)

主键不能为空,非主键可以:

mysql> insert into user1 values(NULL,'张三');
ERROR 1048 (23000): Column 'id' cannot be null
mysql> insert into user1 values(3,NULL); Query OK, 1 row affected (0.00 sec) mysql> select *from user1; +----+--------+ | id | name | +----+--------+ | 1 | 张三 | | 2 | 张三 | | 3 | NULL | +----+--------+ 3 rows in set (0.01 sec)

 

2.联合主键约束

mysql> create table user2(
    -> id int,
    -> name varchar(20),
    -> password varchar(20),
    -> primary key(id,name)
    -> );
Query OK, 0 rows affected (0.01 sec)

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

添加数据,只要主键的两项不全一致就行:

mysql> insert into user2 values(1,'张三','123');
Query OK, 1 row affected (0.01 sec)
mysql> insert into user2 values(2,'张三','123');
Query OK, 1 row affected (0.00 sec)
mysql> insert into user2 values(1,'李四','123');
Query OK, 1 row affected (0.00 sec)

mysql> select *from user2;
+----+--------+----------+
| id | name   | password |
+----+--------+----------+
|  1 | 张三   | 123      |
|  1 | 李四   | 123      |
|  2 | 张三   | 123      |
+----+--------+----------+
3 rows in set (0.00 sec)

但主键不能为空,任何一个都不行:

mysql> insert into user2 values(NULL,'李四','123');
ERROR 1048 (23000): Column 'id' cannot be null

 

3.自增约束 auto increment

mysql> create table user3(
    -> id int primary key auto_increment,
    -> name varchar(20)
    -> );
Query OK, 0 rows affected (0.01 sec)

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

仅添加非主键部分,id默认从1开始:

mysql> insert into user3(name) values('zhangsan');
Query OK, 1 row affected (0.00 sec)

mysql> insert into user3(name) values('zhangsan');
Query OK, 1 row affected (0.00 sec)

mysql> insert into user3(name) values('zhangsan');
Query OK, 1 row affected (0.00 sec)

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

如果对id有定义,可以仅添加一次:

mysql> delete from user3 where name='zhangsan';
Query OK, 3 rows affected (0.00 sec)

mysql> insert into user3 values(202201,'zhangsan');
Query OK, 1 row affected (0.00 sec)

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

mysql> insert into user3(name) values('zhangsan');
Query OK, 1 row affected (0.00 sec)

mysql> select *from user3;
+--------+----------+
| id     | name     |
+--------+----------+
| 202201 | zhangsan |
| 202202 | zhangsan |
| 202203 | zhangsan |
+--------+----------+
3 rows in set (0.00 sec)

 

4.建表后添加与删除主键

mysql> create table user4(
    -> id int,
    -> name varchar(20)
    -> );
Query OK, 0 rows affected (0.00 sec)

mysql> desc user4;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int         | YES  |     | NULL    |       |
| name  | varchar(20) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

添加主键:

mysql> alter table user4 add primary key(id);
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

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

删除主键:

mysql> alter table user4 drop primary key;
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

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

添加和删除联合主键一样的道理:

mysql> alter table user4 add primary key(id,name);
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

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

mysql> alter table user4 drop primary key;
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc user4;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int         | NO   |     | NULL    |       |
| name  | varchar(20) | NO   |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

 

修改主键约束,和添加主键差不多,一般不用这种方法:

mysql> alter table user4 modify id int primary key;
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

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

 

5.唯一约束------约束修饰的字段的值不可以重复(可以为空)

   5.1建表后添加

mysql> create table user5(
    -> id int,
    -> name varchar(20)
    -> );
Query OK, 0 rows affected (0.01 sec)

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

mysql> desc user5;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int         | YES  |     | NULL    |       |
| name  | varchar(20) | YES  | UNI | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

添加数据(唯一约束下的name字段不能重复):

mysql> insert into user5 values(1,'zhangsan');
Query OK, 1 row affected (0.00 sec)

mysql> insert into user5 values(1,'zhangsan');
ERROR 1062 (23000): Duplicate entry 'zhangsan' for key 'user5.name'
mysql> insert into user5 values(1,'lisi');
Query OK, 1 row affected (0.00 sec)

mysql> insert into user5 values(1,'NULL');
Query OK, 1 row affected (0.00 sec)

mysql> select *from user5;
+------+----------+
| id   | name     |
+------+----------+
|    1 | zhangsan |
|    1 | lisi     |
|    1 | NULL     |
+------+----------+
3 rows in set (0.00 sec)

 

   5.2建表时添加

mysql> create table user6(
    -> id int,
    -> name varchar(20),
    -> unique(name)
    -> );
Query OK, 0 rows affected (0.01 sec)

mysql> desc user6;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int         | YES  |     | NULL    |       |
| name  | varchar(20) | YES  | UNI | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

mysql> create table user7(
    -> id int,
    -> name varchar(20) unique
    -> );
Query OK, 0 rows affected (0.01 sec)

mysql> desc user7;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int         | YES  |     | NULL    |       |
| name  | varchar(20) | YES  | UNI | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.01 sec)

 

   5.3添加多个唯一约束(依旧是两个不完全一样就行)

mysql> create table user8(
    -> id int,
    -> name varchar(20),
    -> unique(id,name)
    -> );
Query OK, 0 rows affected (0.01 sec)

mysql> desc user8;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int         | YES  | MUL | NULL    |       |
| name  | varchar(20) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

mysql> insert into user8 values(1,'zhangsan');
Query OK, 1 row affected (0.00 sec)

mysql> insert into user8 values(2,'zhangsan');
Query OK, 1 row affected (0.00 sec)

mysql> select *from user8;
+------+----------+
| id   | name     |
+------+----------+
| NULL | NULL     |
|    1 | zhangsan |
|    2 | zhangsan |
+------+----------+
3 rows in set (0.01 sec)

 

   5.4删除唯一约束

mysql> alter table user7 drop index name;
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

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

 

   5.5修改唯一约束

mysql> alter table user7 modify name varchar(20) unique;
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc user7;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int         | YES  |     | NULL    |       |
| name  | varchar(20) | YES  | UNI | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

 

6.非空约束 not null

mysql> create table user9(
    -> id int,
    -> name varchar(20) not null
    -> );
Query OK, 0 rows affected (0.01 sec)

mysql> desc user9;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int         | YES  |     | NULL    |       |
| name  | varchar(20) | NO   |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
mysql> insert into user9(id) values(1);
ERROR 1364 (HY000): Field 'name' doesn't have a default value
mysql> insert into user9 values(1,'zhangsan');
Query OK, 1 row affected (0.00 sec)

mysql> insert into user9(name) values('lisi');
Query OK, 1 row affected (0.00 sec)

mysql> select *from user9;
+------+----------+
| id   | name     |
+------+----------+
|    1 | zhangsan |
| NULL | lisi     |
+------+----------+
2 rows in set (0.00 sec)

 

7.默认约束--------当我们插入字段值的时候,如果没有传值,就会使用默认值

mysql> insert into user10(id,name) values(1,'zhangsan');
Query OK, 1 row affected (0.00 sec)

mysql> select *from user10;
+------+----------+------+
| id   | name     | age  |
+------+----------+------+
|    1 | zhangsan |   10 |
+------+----------+------+
1 row in set (0.00 sec)

mysql> insert into user10 values(1,'zhangsan',19);
Query OK, 1 row affected (0.00 sec)

mysql> select *from user10;
+------+----------+------+
| id   | name     | age  |
+------+----------+------+
|    1 | zhangsan |   10 |
|    1 | zhangsan |   19 |
+------+----------+------+
2 rows in set (0.00 sec)

 

8.外键约束----------涉及到两个表(主表、副表)

mysql> create table classes(
    -> id int primary key,
    -> name varchar(20)
    -> );
Query OK, 0 rows affected (0.01 sec)

mysql> create table students(
    -> id int primary key,
    -> name varchar(20),
    -> class_id int,
    -> foreign key(class_id) references classes(id)
    -> );
Query OK, 0 rows affected (0.01 sec)

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

mysql> desc students;
+----------+-------------+------+-----+---------+-------+
| Field    | Type        | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| id       | int         | NO   | PRI | NULL    |       |
| name     | varchar(20) | YES  |     | NULL    |       |
| class_id | int         | YES  | MUL | NULL    |       |
+----------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
mysql> insert into classes values(1,'1班');
Query OK, 1 row affected (0.00 sec)
mysql> insert into classes values(2,'2班');
Query OK, 1 row affected (0.00 sec)
mysql> insert into classes values(3,'3班');
Query OK, 1 row affected (0.00 sec)
mysql> insert into classes values(4,'4班');
Query OK, 1 row affected (0.00 sec)

mysql> select *from classes;
+----+------+
| id | name |
+----+------+
|  1 | 1班  |
|  2 | 2班  |
|  3 | 3班  |
|  4 | 4班  |
+----+------+
4 rows in set (0.00 sec)

--主表classes中没有的数据值,在副表中是不可以使用的

--主表中的记录被副表引用,是不可以被删除的

mysql> insert into students values(1001,'张三',1);
Query OK, 1 row affected (0.00 sec)
mysql> insert into students values(1002,'张三',2);
Query OK, 1 row affected (0.01 sec)
mysql> insert into students values(1003,'张三',3);
Query OK, 1 row affected (0.00 sec)
mysql> insert into students values(1004,'张三',4);
Query OK, 1 row affected (0.00 sec)

mysql> insert into students values(1005,'张三',5);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`test`.`students`, CONSTRAINT `students_ibfk_1` FOREIGN KEY (`class_id`) REFERENCES `classes` (`id`))

mysql
> select *from students; +------+--------+----------+ | id | name | class_id | +------+--------+----------+ | 1001 | 张三 | 1 | | 1002 | 张三 | 2 | | 1003 | 张三 | 3 | | 1004 | 张三 | 4 | +------+--------+----------+ 4 rows in set (0.00 sec)

 

推荐阅读