MySQL--表完整性约束

前言:本博客仅作记录学习使用,部分图片出自网络,如有侵犯您的权益,请联系删除

作用:用于保证数据的完整性和一致性

约束条件说明
PRIMARY KEY (PK)该字段为该表的主键,可以唯一的标识记录,不可以为空 UNIQUE + NOT NULL
FOREIGN KEY (FK)该字段为该表的外键,实现表与表之间的关联
NULL是否允许为空,默认为NULL
NOT NULL该字段不能为空,可以修改
UNIQUE KEY (UK)该字段的值是唯一的,可以为空,一个表中可以有多个UNIQUE KEY
AUTO_INCREMENT该字段的值自动增长(整数类型,而且为主键)
DEFAULT为该字段设置默认值
UNSIGNED无符号,正数

一、PRIMARY KEY 主键

  • 每张表里只能有一个主键,不能为空,而且唯一,主键保证记录的唯一性,主键自动为NOT NULL
  • 一个 UNIQUE KEY又是一个NOT NULL的时候,那么它被当做PRIMARY KEY主键。

1、定义主键的方式

 # 表存在,添加约束:
 mysql> alter table test1 add primary key (hostname);
 ​
 # 创建表并指定约束
 mysql> create table test2(hostname char(20),ip char(150),primary key(hostname));
 mysql> desc test2;
 +----------+-----------+------+-----+---------+-------+
 | Field    | Type      | Null | Key | Default | Extra |
 +----------+-----------+------+-----+---------+-------+
 | hostname | char(20)  | NO   | PRI | NULL    |       |
 | ip       | char(150) | YES  |     | NULL    |       |
 +----------+-----------+------+-----+---------+-------+

2、唯一性

 mysql> insert into test2(hostname,ip) value('ddd.com','10.0.0.1');
 mysql> insert into test2(hostname,ip) value('ddd.com','10.0.0.1');
 ERROR..:Duplicate entry 'ddd.com' for key 'PRIMARY'

3、不为空

 mysql> insert into test2(ip) values('10.0.0.2');
 ERROR: 1364 (HY000):Filed 'hostname' doesn't have a default value

4、删除主键

删除一张表中的主键语法如下:

 mysql> alter table tab_name drop primary key;

主键被删除之后,这个字段仍然不允许为空值

二、AUTO_INCREMENT 自增

自动编号,且必须与主键组合使用;默认情况下,起始值为1,每次的增量为1。当插入记录时, 如果为AUTO_INCREMENT数据列明确指定了一个数值,则会出现两种情况:

  • 若插入值与已有编号重复,则会出现出错信息,因为AUTO_INCREMENT数据列的值必须是唯一 的;
  • 若插入值大于已编号值,则会把该插入到数据列中,并使在下一个编号将从这个新值开始递增。 也就是说,可以跳过一些编号。如果自增序列的最大值被删除了,则在插入新记录时,该值不会被重用。 (每张表只能有一个字段为自增) (成了key才可以自动增长)

1、定义方法

 mysql> create table department(
     dept_id int primary key auto_increment,
     dept_name varchar(30),
     comment varchar(50)
     );
 mysql> desc department;
 +-----------+-------------+------+-----+---------+----------------+
 | Field     | Type        | Null | Key | Default | Extra          |
 +-----------+-------------+------+-----+---------+----------------+
 | dept_id   | int(11)     | NO   | PRI | NULL    | auto_increment |
 | dept_name | varchar(30) | YES  |     | NULL    |                |
 | comment   | varchar(50) | YES  |     | NULL    |                |
 +-----------+-------------+------+-----+---------+----------------+

2、插入值

 mysql> insert into department(dept_name,comment) values('tom','test'),('jack','test2');
 mysql> select * from department;
 +---------+-----------+---------+
 | dept_id | dept_name | comment |
 +---------+-----------+---------+
 |       1 | tom       | test    |
 |       2 | jack      | test2   |
 +---------+-----------+---------+

3、删除自动增长

 mysql> alter table department change dept_id dept_id int not null;
 mysql> desc department;
 +-----------+-------------+------+-----+---------+-------+
 | Field     | Type        | Null | Key | Default | Extra |
 +-----------+-------------+------+-----+---------+-------+
 | dept_id   | int(11)     | NO   | PRI | NULL    |       |
 | dept_name | varchar(30) | YES  |     | NULL    |       |
 | comment   | varchar(50) | YES  |     | NULL    |       |
 +-----------+-------------+------+-----+---------+-------+
 ​
 # 再次插入数据,报错:
 mysql> insert into department(dept_name,comment) values('tom','test1'),('jack','test2');
 ERROR 1364 (HY000): Field 'dept_id' doesn't have a default value

三、UNIQUE KEY

字段添加唯一约束之后,该字段的不能重复,也就是说在一列当中不能出现一样的值

1、定义方法

 # 表已经存在的话:
 mysql> alter table department add unique key (dept_id);
 ​
 # 表不存在的话:
 mysql> create table department(
     dept_id int,
     dept_name varchar(30) unique,
     comment varchar(50)
     );
     
 mysql> desc  department;
 +-----------+-------------+------+-----+---------+-------+
 | Field     | Type        | Null | Key | Default | Extra |
 +-----------+-------------+------+-----+---------+-------+
 | dept_id   | int(11)     | YES  |     | NULL    |       |
 | dept_name | varchar(30) | YES  | UNI | NULL    |       |
 | comment   | varchar(50) | YES  |     | NULL    |       |
 +-----------+-------------+------+-----+---------+-------+

2、值不重复

在设置了unique的字段的值不能重复,其余字段可以重复;

 mysql> insert into department(dept_id,dept_name,comment) value(1,"tom","good");
 Query OK, 1 row affected (0.01 sec)
 ​
 # dept_name与上一个重复,报错
 mysql> insert into department(dept_id,dept_name,comment) value(2,"tom","good");
 ERROR 1062 (23000): Duplicate entry 'tom' for key 'dept_name'
 ​
 mysql> insert into department(dept_id,dept_name,comment) value(2,"jim","good");
 Query OK, 1 row affected (0.00 sec)

3、删除unique

 mysql> alter table department drop index dept_name;
 mysql> desc department;
 +-----------+-------------+------+-----+---------+-------+
 | Field     | Type        | Null | Key | Default | Extra |
 +-----------+-------------+------+-----+---------+-------+
 | dept_id   | int(11)     | YES  |     | NULL    |       |
 | dept_name | varchar(30) | YES  |     | NULL    |       |
 | comment   | varchar(50) | YES  |     | NULL    |       |
 +-----------+-------------+------+-----+---------+-------+

四、NULL与NOT NULL

  • 是否允许为空,默认NULL可设置NOT NULL,字段不允许为空,必须赋值
  • 字段是否有默认值,缺省的默认值是NULL,如果插入记录时不给字段赋值,此字段使用默认值

1、NOT NULL

 # 只能选择male和female,不允许为空,默认是male
 sex enum('male','female') not null default 'male'   

not null定义方法:

 mysql> create table test(id int(5),name varchar(10),sex enum('male','female') not null default 'male');
 mysql> insert into test(id,name) values(1,'tom');
 mysql> select * from test;
 +------+------+------+
 | id   | name | sex  |
 +------+------+------+
 |    1 | tom  | male |
 +------+------+------+
 1 row in set (0.00 sec)

删除不允许为空和默认值:

 mysql> alter table test change sex sex enum('male','female');

2、NULL:

 mysql> create table test(id int(5),name varchar(10),age int(5));
 mysql> desc test;
 +-------+-------------+------+-----+---------+-------+
 | Field | Type        | Null | Key | Default | Extra |
 +-------+-------------+------+-----+---------+-------+
 | id    | int(5)      | YES  |     | NULL    |       |
 | name  | varchar(10) | YES  |     | NULL    |       |
 | age   | int(5)      | YES  |     | NULL    |       |
 +-------+-------------+------+-----+---------+-------+
 mysql> insert into test(id,name) values(1,'tom');
 mysql> select * from test;
 +------+------+------+
 | id   | name | age  |
 +------+------+------+
 |    1 | tom  | NULL |
 +------+------+------+

五、UNSIGNED

整数类型有可选的UNSIGNED属性,表示不允许负值,这大致上可以使正数的上限提高一倍

可以使用这几种整数类型:TINYINT,SMALLINT,MEDIUMINT,INT,BIGINT。分别使用8,16,24,32,64位存储空间;它们可以存储的值的范围从-2(n-1)到2(n-1)-1,其中n是存储空间的位数

1、定义方法

 mysql> create table guo(id int(1) default null,qq int(5) unsigned default null);
 Query OK, 0 rows affected (0.00 sec)
 ​
 # id为未指定unsigned,而qq为指定unsigned;先对id列插入数据;根据计算得2(n-1)-1为2147483647
 mysql> insert into guo(id) values(2147483647);
 Query OK, 1 row affected (0.01 sec)
 ​
 # 插入2147483648则提示超出范围
 mysql> insert into guo(id) values(2147483648);
 ERROR 1264 (22003): Out of range value for column 'id' at row 1
 ​
 # 下面对unsigned列进行插入,范围应该为2(n-1)+2(n-1)-1为4294967295
 mysql> insert into guo(qq) values(-2147483648);
 ERROR 1264 (22003): Out of range value for column 'qq' at row 1
 ​
 mysql> insert into guo(qq) values(4294967296);
 ERROR 1264 (22003): Out of range value for column 'qq' at row 1
 ​
 mysql> insert into guo(qq) values(4294967295);
 Query OK, 1 row affected (0.00 sec)

MySQL可以为整数指定宽度,例如int(11),对大多数应用这是没有意义的:它不会限制值的合法范围, 只是规定了MySQL的一些交互工具(例如MySQL命令行客户端)用来显示字符的个数。对于存储和计算来说,int(1)和int(20)是相同的。

六、字符集问题

参考链接:字符集详解(学习,看一篇就够了)-CSDN博客 了解

1、修改字符集

在创建表的最后面指定一下: default charset=utf8 #可以指定中文

2、查看字符集

 mysql> show variables like '%char%';
 +--------------------------+-----------------------------+
 | Variable_name            | Value                       |
 +--------------------------+-----------------------------+
 | character_set_client     | utf8                        |
 | character_set_connection | utf8                        |
 | character_set_database   | latin1                      |
 | character_set_filesystem | binary                      |
 | character_set_results    | utf8                        |
 | character_set_server     | latin1                      |
 | character_set_system     | utf8                        |
 | character_sets_dir       | /data/mysql/share/charsets/ |
 +--------------------------+-----------------------------+

3、设置字符集

# 未指定之前,插入,不支持中文,报错
mysql> insert into test(id,name) values(1,'张三');
ERROR 1366 (HY000): Incorrect string value: '\xE5\xBC\xA0\xE4\xB8\x89' for column 'name' at row 1

# 执行如下语句将字符集设置为utf8
mysql> set global 要修改的字段=utf8
---------------------------------
# 创建表格式指定字符集为utf-8
mysql> create table test(id int(2),name char(5),age int(4)) default charset=utf8;
Query OK, 0 rows affected (0.01 sec)

mysql> desc test;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id    | int(2)  | YES  |     | NULL    |       |
| name  | char(5) | YES  |     | NULL    |       |
| age   | int(4)  | YES  |     | NULL    |       |
+-------+---------+------+-----+---------+-------+
mysql> insert into test(id,name) values(1,'张三');

4、修改表的字符集

命令行修改:

mysql> alter table 表名 default character set utf8;

配置文件设置默认字符集:

来到MySQL的安装目录下找到my.cnf文件

# 在[mysql]下方添加一句:
default-character-set=utf8

# 在[mysqld]下方添加两句:
collation-server=utf8_general_ci
character-set-server=utf8

# 停止mysql,重新启动mysql,再次执行语句
mysql> show variables like '%char%';

# 注意:
# 这种方式并不能修改已经创建的数据库或表的字符集,修改的是之后创建的数据库或表的默认字符集

七、默认约束

1、添加/删除默认约束

# 首先创建一个表:
mysql> create table user(id int not null,name varchar(20),number int,primary key(id));
mysql> desc user;
+--------+-------------+------+-----+---------+-------+
| Field  | Type        | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| id     | int(11)     | NO   | PRI | NULL    |       |
| name   | varchar(20) | YES  |     | NULL    |       |
| number | int(11)     | YES  |     | NULL    |       |
+--------+-------------+------+-----+---------+-------+

# 设置默认值
mysql> alter table user alter number set default 0;
Query OK, 0 rows affected (0.00 sec)
Records: 0  Duplicates: 0  Warnings: 0
# 也可以这样修改
mysql> alter table user change number num int(6) not null default 3;

mysql> desc user;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | NO   | PRI | NULL    |       |
| name  | varchar(20) | YES  |     | NULL    |       |
| num   | int(6)      | NO   |     | 3       |       |
+-------+-------------+------+-----+---------+-------+

# 插入值
mysql> alter table user change id id int not null auto_increment;
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

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

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

mysql> select * from user;
+----+------+--------+
| id | name | number |
+----+------+--------+
|  1 | rock |      3 |
|  2 | rock |      3 |
+----+------+--------+

# 删除默认值
mysql> alter table user alter number drop default;

八、外键

MySQL外键约束:

  • 外键约束(FOREIGN KEY,缩写FK)是用来实现数据库表的参照完整性约束的;
  • 外键约束可以是两张表紧密的结合起来,特别是针对修改或者删除的级联操作时,会保证数据的完整性;

级联cascade)在计算机科学里指多个对象之间的映射关系,建立数据之间的级联关系提高管理效率)

外键是指表中某个字段的值依赖于另一张表中的某个字段的值,而被依赖的字段必须具有主键约束或者唯一约束。被依赖的表我们通常称之为父表或者主表,设置外键约束的表。称之为子表或者从表

示例:创建一个班级表,插入数据:

create table class (
	cno int(4) auto_increment,
	cname varchar(12) not null,
	room varchar(4),
	primary key(cno)
) default charset=utf8;

insert into class values (null,'java001',101);
insert into class values (null,'java002',102);
insert into class values (null,'java001',101);

select * from class;
+-----+---------+------+
| cno | cname | room |
+-----+---------+------+
| 1 | java001 | 101 |
| 2 | java002 | 102 |
| 3 | java001 | 101 |
+-----+---------+------+

创建一个学生表:

create table student(
sno int(6) primary key auto_increment,
name varchar(12),
sex char(1),
age int(2),
classno int(4),
constraint fk_stu_classno foreign key (classno) references class(cno)
) default charset=utf8;

insert into student values(null,'张三','男',23,1);
insert into student values(null,'李四','男',24,1);
insert into student values(null,'王五','男',16,2);

select * from student;
+-----+--------+------+------+---------+
| sno | name | sex | age | classno |
+-----+--------+------+------+---------+
| 1 | 张三 | 男 | 23 | 1 |
| 2 | 李四 | 男 | 24 | 1 |
| 3 | 王五 | 男 | 16 | 2 |
+-----+--------+------+------+---------+

尝试class表操作,删除,更改1班。都会失败:

mysql> delete from class where cno=2;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key
constraint fails (`qf1`.`student`, CONSTRAINT `fk_stu_classno` FOREIGN KEY
(`classno`) REFERENCES `class` (`cno`))

mysql> update class set cno=5 where cno=2;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key
constraint fails (`qf1`.`student`, CONSTRAINT `fk_stu_classno` FOREIGN KEY
(`classno`) REFERENCES `class` (`cno`))

因为存在外键,class表中cno=1中有学生存在,所以删除不了。 如果想删除1班,手动先对1班学生进行处理(删除或者清空外键)

​
mysql> update student set classno=null where classno=1;
Query OK, 2 rows affected (0.00 sec)
Rows matched: 2 Changed: 2 Warnings: 0

mysql> select * from student;
+-----+--------+------+------+---------+
| sno | name   | sex  | age  | classno |
+-----+--------+------+------+---------+
|   1 | 张三   | 男   |   23 |    NULL |
|   2 | 李四   | 男   |   24 |    NULL |
|   3 | 王五   | 男   |   16 |       2 |
+-----+--------+------+------+---------+

​

再次删除cno=1的班级:

mysql> delete from class  where cno=1;
mysql> select * from class;
+-----+---------+------+
| cno | cname   | room |
+-----+---------+------+
|   2 | java002 | 102  |
|   3 | java001 | 101  |
+-----+---------+------+

修改外键设置

外键要修改只能先删除再添加;如果希望在更新班级号的时候,可以直接更新学生的班级编号;希望在删除某个班级的时候,清空学生的班级编号;

删除外键和添加外键

mysql> alter table student drop foreign key fk_stu_classno;
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

修改外键设置

mysql> alter table student add constraint fs_stu_classno foreign key(classno) references class(cno) on delete set null on update cascade;

mysql> desc student;
+---------+-------------+------+-----+---------+----------------+
| Field   | Type        | Null | Key | Default | Extra          |
+---------+-------------+------+-----+---------+----------------+
| sno     | int(6)      | NO   | PRI | NULL    | auto_increment |
| name    | varchar(12) | YES  |     | NULL    |                |
| sex     | char(1)     | YES  |     | NULL    |                |
| age     | int(2)      | YES  |     | NULL    |                |
| classno | int(4)      | YES  | MUL | NULL    |                |
+---------+-------------+------+-----+---------+----------------+

致谢

在此,我要对所有为知识共享做出贡献的个人和机构表示最深切的感谢。同时也感谢每一位花时间阅读这篇文章的读者,如果文章中有任何错误,欢迎留言指正。 

学习永无止境,让我们共同进步!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小李学不完

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值