MySQL字段约束条件
-字段约束条件-
约束条件 与 数据长度一样都是可选参数
作用:用于保证数据的完整性和一致性
约束条件属于表结构,可以通过desc 表名;
来进行查看
类型 | 作用 |
---|---|
PRIMARY KEY (PK) | 标识该字段为该表的主键 |
FOREIGN KEY (FK) | 标识该字段为该表的外键 |
NOT NULL | 标识该字段不能为空 |
UNIQUE KEY (UK) | 标识该字段的值是唯一 的 |
AUTO_INCREMENT | 标识该字段的值自动增长 (整数类型,而且为主键) |
DEFAULT | 为该字段设置默认值 |
UNSIGNED | 无符号 |
ZEROFILL | 使用0填充 |
1.无符号UNSIGNED、0填充ZEROFILL
unsigned 表示无符号
id int unsigned
zerofill 仅用于显示,当不满足5位时,按照左边补0,例如:00002;满足时,正常显示。
id int(5) zerofill
2.非空 not null
not null
代表该字段不能为空,必须为该字段插入值,如果不插入值则会使用默认值,如果默认值为null
则报错
(1)所有的字段类型,在不加约束条件的情况下默认都可以为空
# 建立数据库 db3
mysql> create database db3;
Query OK, 1 row affected (0.02 sec)
# 切换库db3
mysql> use db3
Database changed
# 建表t1
mysql> create table t1(id int,name varchar(16));
Query OK, 0 rows affected (0.06 sec)
# 查看表结构,默认值都为null可以为空
mysql> desc t1;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| name | varchar(16) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.01 sec)
# 插入语句 insert into 表名(字段名) values(记录);
mysql> insert into t1(id) values(1);
Query OK, 1 row affected (0.02 sec)
mysql> insert into t1(name) values('jason');
Query OK, 1 row affected (0.02 sec)
mysql> insert into t1(name,id) values('kevin',2);
Query OK, 1 row affected (0.03 sec)
mysql> select * from t1;
+------+-------+
| id | name |
+------+-------+
| 1 | NULL | -- 可以为null
| NULL | jason |
| 2 | kevin |
+------+-------+
3 rows in set (0.00 sec)
(2)not null非空
# sql语句创建表
create table t2(
id int,
name varchar(16) not null
);
# 插入值
insert into t2(id) values(1);
insert into t2(name) values('jason');
insert into t2 values(1,''); --只要写了东西就默认为非空
insert into t2 values(2,null);
例:--只要写了东西就默认为非空
# 建立表t2
mysql> create table t2(
-> id int,
-> name varchar(16) not null
-> );
Query OK, 0 rows affected (0.06 sec)
# 插入值
mysql> insert into t2(id) values(1);
ERROR 1364 (HY000): Field 'name' doesn't have a default value
mysql> insert into t2(name) values('jason');
Query OK, 1 row affected (0.03 sec)
# 只要有插值的动作,就算非空
mysql> insert into t2 values(1,'');
Query OK, 1 row affected (0.02 sec)
mysql> desc t2;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| name | varchar(16) | NO | | NULL | |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
# 插入null 由于约束条件为not null则报错
mysql> insert into t2 values(2,null);
ERROR 1048 (23000): Column 'name' cannot be null
3.默认值Default
默认值用于在创建表时为字段设置默认值,当插入时可以省略该字段的数据插入而去使用设定的默认值,如不设定默认值则为null
# 建表
create table t3(
id int default 333, -- 不填数据的情况下默认为 333
name varchar(16) default '铎铎' -- 不填数据的情况下默认为'铎铎'
);
insert into t3 values(2,null)
mysql> desc t3;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | YES | | 333 | |
| name | varchar(16) | YES | | 铎铎 | |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
4.唯一值Unique
(1)单列唯一
单列唯一是指该字段下的值不能重复
# 建立表
create table t4(
id int,
name varchar(32) unique -- name的值唯一不能重复
);
insert into t4 values(1,'duoduo'),(2,'lulu');
# 插入 1,'duoduo'
mysql> insert into t4 values(1,'duoduo');
Query OK, 1 row affected (0.03 sec)
# 插入 1,'duoduo' 2,'lulu'
mysql> insert into t4 values(1,'duoduo'),(2,'lulu');
ERROR 1062 (23000): Duplicate entry 'duoduo' for key 'name'
# 报错duoduo已经存在了,不能重复
# 插入 1,'lulu'
mysql> insert into t4 values(1,'lulu');
Query OK, 1 row affected (0.02 sec)
# 插入 ,'kdka'
mysql> insert into t4 values(1,'kdka');
Query OK, 1 row affected (0.02 sec)
mysql> select * from t4;
+------+--------+
| id | name |
+------+--------+
| 1 | duoduo |
| 1 | lulu |
| 1 | kdka |
+------+--------+
3 rows in set (0.00 sec)
# id字段可以不唯一可以重复,name字段有约束条件unique所以不能重复
(2)联合唯一
unique(field1,field2,field3...)
联合唯一:field字段对应的值之间的组合不能重复
# 建表
create table t5(
id int,
ip varchar(32), -- 字符括号内填写的数字最好为16的倍数,并不要超过255
port varchar(32),
unique(ip,port) -- 指定ip和port的组合不能重复
);
# 插入值 两两组合,只要不重复则可以插入成功
insert into t5 values(1,'127.0.0.1','8080'),(2,'127.0.0.1','8081'),(3,'127.0.0.2','8080');
# 将id=1 中的两组颠倒过来,也可以插入成功,说明顺序对应的字段名也是组合的一部分
insert into t5 values(4,'8080','127.0.0.1');
# 查看t5
mysql> select * from t5;
+------+-----------+-----------+
| id | ip | port |
+------+-----------+-----------+
| 1 | 127.0.0.1 | 8080 |
| 2 | 127.0.0.1 | 8081 |
| 3 | 127.0.0.2 | 8080 |
| 4 | 8080 | 127.0.0.1 |
+------+-----------+-----------+
4 rows in set (0.00 sec)
5.主键Primary key
(1)主键的特点
1)主键单从约束条件层面上而言主键相当于not nul
l + unque
==>> 非空且唯一
2)InnoDB存储引擎规定了所有的表都必须有且只有一个主键,InnoDB会根据主键锁约束字段的值来建立索引,建立表的整体结构,加速查询
# 建表
create table t6(
id int primary key, -- id为主键,此时id不可为空并且值唯一
name varchar(32)
);
insert into t6(name) values('duoduo');
insert into t6 values(1,'亚索');
insert into t6 values(2,'亚索');
# 不输入id报错 由于id约束条件为主键,则id不可以为空
mysql> insert into t6(name) values('duoduo');
ERROR 1364 (HY000): Field 'id' doesn't have a default value
# 输入 1,'亚索'
mysql> insert into t6 values(1,'亚索');
Query OK, 1 row affected (0.02 sec)
# 输入 2,'亚索' name字段可以重复
mysql> insert into t6 values(2,'亚索');
Query OK, 1 row affected (0.02 sec)
# 输入 1,'duoduo' id字段为主键不可以重复
mysql> insert into t6 values(1,'duoduo');
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'
mysql> select * from t6;
+----+--------+
| id | name |
+----+--------+
| 1 | 亚索 |
| 2 | 亚索 |
+----+--------+
2 rows in set (0.00 sec)
(2)主键的作用:
1)主键是组织数据的重要条件
2)主键可以加快数据的查找速度(索引)
(3)InnoDB引擎中主键的特性
1)当表中没有主键也没有其他非空且唯一的字段的情况下,也就是表中没有显式的设置主键,InnoDB
会采用一个隐藏的字段作为表的主键,否则对于该表的数据查询只能一行行查找,速度很慢
2)当表中没有主键但是有其他非空且唯一的字段,那么会从上往下讲第一个非空且唯一的该字段自动升级为主键
# 建表
create table t7(
id int,
age int not null unique,
level int not null unique,
phonenum bigint not null unique
);
mysql> desc t7;
+----------+------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| age | int(11) | NO | PRI | NULL | |
| level | int(11) | NO | UNI | NULL | |
| phonenum | bigint(20) | NO | UNI | NULL | |
+----------+------------+------+-----+---------+-------+
4 rows in set (0.00 sec)
则会发现从上往往下,3个非空且唯一的字段中,第一个age自动升级为主键
在创建表的时候应该有一个字段应该来标识字段的唯一性,通常情况下该字段就是编号字段,我们可以将该编号字段设置为主键
该字段可以叫
id uid zid gid...
6.自增auto_increment
自增特点:
1)该约束条件不能单独出现,并且一张表中只能出现一次,自增主要就是配合主键一起用
2)自增字段的记录不会因为数据的删除而回退,永远自增往前
如果自己设置了自增字段的记录为更大的数,则之后就在该数字的基础上继续自增
# 建表
create table t8(
id int primary key auto_increment,
name varchar(32)
);
# 插入值
mysql> insert into t8 values(1,'aa');
...
# 设定id=55
mysql> insert into t8 values(55,'dd');
# 再插入值
mysql> insert into t8(name) values('ff');
mysql> select * from t8;
+----+------+
| id | name |
+----+------+
| 1 | aa |
| 2 | bb |
| 3 | cc |
| 4 | dd |
| 55 | dd |
| 56 | ff |
+----+------+
# 则发现此时 id自增列从55开始自增
# 设定id=2000
mysql> insert into t8 values(2000,'mm');
mysql> insert into t8(name) values('ff');
mysql> select * from t8;
+------+------+
| id | name |
+------+------+
| 1 | aa |
| 2 | bb |
| 3 | cc |
| 4 | dd |
| 55 | dd |
| 56 | ff |
| 2000 | mm |
| 2001 | ff |
| 2002 | ff |
+------+------+
# 则发现此时 id自增列从2000开始自增
# 删除前面的值之后再添加新的值
mysql> delete from t8 where id<2003;
Query OK, 2 rows affected (0.02 sec)
mysql> insert into t8(name) values('ff');
Query OK, 1 row affected (0.02 sec)
mysql> select * from t8;
+------+------+
| id | name |
+------+------+
| 2003 | ff |
+------+------+
#id自增列还是从2003开始自增
7.外键
1.使用外键的目的
比如我们需要一张员工表,写入数据库中
这张表在表达上有以下缺点
(1)语义不明确,描述不清晰,员工表中包含了部门的信息
(2)数据过于冗余,部门的信息重复浪费了存储空间
(3)数据的扩展性较差,修改部门的信息相关员工的信息都要修改
那么我们可以将员工表和部门表独立开,这样表达简洁明了,扩展起来也方便,但是部门和与员工之间就没有联系了
这时候建立彼此之间的联系,就需要外键Foreign Key来建立表与表之间数据的联系
综上,外键字段:用于标识数据与数据之间关系的
2.表与表之间的关系
(1)外键的关系判断:
表与表的关系或者说是表与表之间数据的关系
(2)关系总共有四种:
一对多、多对多、 一对一、 没有关系
(3)关系的判断法则可以采用 换位思考:
也就是站在表A的视角,思考是否A的多个数据可以属于表B中的1个数据
比如 :
员工角度:多个员工 属于 一个部门 √
部门角度:多个部门 拥有 一个员工×
==>得出 彼此之间的关系是 一对多
针对一对多关系,
外键
应该建在多
的一方
3.外键字段的建立
可以先定义出表的普通字段,之后在考虑外键字段的添加
(1)一对多
一对多应该满足
1.创建表的时候一定要先创建被关联表
2.录入表数据的时候一定先录入被关联表(数据库层面的约束非常强烈)
3.修改数据的时候,外键字段无法修改和删除,也就是需要先解除关系
# 建立员工表
create table emp(
id int primary key auto_increment,
name varchar(32),
age int
dep_id int,
foreign key(dep_id) references dep(id) --
);
# 建立部门表
create table dep(
id int primary key auto_increment,
dep_name varchar(32),
dep_desc varchar(32)
);
例子.修改数据的时候,外键字段无法修改和删除,也就是需要先解除关系
针对3有简化措施>>可以采用 级联更新 和 级联删除 的约束条件
及联更新
on update cascade
:只会更改ID及联删除
on delete cascade
:被关联的表ID删除后,关联表的相关记录也会被删除
# 创建外键时候添加及联更新和及联删除的约束条件
create table emp(
id int primary key auto_increment,
name varchar(32),
age int
dep_id int,
foreign key(dep_id) references dep(id)
on update cascade
on delete cascade
);
注意:外键的特性是强耦合,并非解耦合
所以实际项目中当表较多的情况,我们可能不会使用外键,而是使用代码建立表与表之间的逻辑关系
(2)多对多
以电影和电影导演来说
电影角度:多个电影 属于 一个导演 √`
导演角度:多个导演 执导 一部电影 √
==>得出 彼此之间的关系是 多对多
# 创建电影表
create table film(
id int primary key auto_increment,
name varchar(64)
);
# 创建导演表
create table director(
id int primary key auto_increment,
name varchar(64)
);
# 将外键创立成表FilmTODirect
create table filmtodirect(
id int primary key auto_increment,
file_id int,
foreign key(file_id) references film(id)
on update cascade
on delete cascade,
director_id int,
foreign key(director_id) references director(id)
on update cascade
on delete cascade
);
# 插入数据
insert into director(id,name) values
(1,'徐克'),
(2,'陈凯歌'),
(3,'林超贤'),
(4,'周星驰'),
(5,'吴宇森');
insert into film(id,name) values
(1,'长津湖1'),
(2,'长津湖2'),
(3,'西游伏妖篇'),
(4,'义胆群英'),
(5,'英雄本色3');
insert into filmtodirect(id,file_id,director_id) values
(1,1,1),
(2,1,2),
(3,1,3),
(4,2,1),
(5,3,1),
(6,3,4),
(7,4,1),
(8,4,4),
(9,5,1),
(10,5,5);
mysql> select * from film;
+----+-----------------+
| id | name |
+----+-----------------+
| 1 | 长津湖1 |
| 2 | 长津湖2 |
| 3 | 西游伏妖篇 |
| 4 | 义胆群英 |
| 5 | 英雄本色3 |
+----+-----------------+
5 rows in set (0.00 sec)
mysql> select * from director;
+----+-----------+
| id | name |
+----+-----------+
| 1 | 徐克 |
| 2 | 陈凯歌 |
| 3 | 林超贤 |
| 4 | 周星驰 |
| 5 | 吴宇森 |
+----+-----------+
5 rows in set (0.00 sec)
mysql> select * from filmtodirect;
+----+---------+-------------+
| id | file_id | director_id |
+----+---------+-------------+
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 1 | 3 |
| 4 | 2 | 1 |
| 5 | 3 | 1 |
| 6 | 3 | 4 |
| 7 | 4 | 1 |
| 8 | 4 | 4 |
| 9 | 5 | 1 |
| 10 | 5 | 5 |
+----+---------+-------------+
10 rows in set (0.00 sec)
(3)一对一
以用户和用户详情表来说
用户角度:多个用户 属于 一个详情 x
用户详情角度:多个详情 属于 一个用户 x
==>得出 不可以 彼此之间的关系是 没有关系
或者是 一对一
,明显是一对一
这时候外键在哪个表添加都没有关系,而最好添加在存储热数据的表中,便于查找
# 创建用户表表
create table customer(
id int primary key auto_increment,
name varchar(20)
);
# 创建用户详情表
create table detail(
id int primary key auto_increment,
gender varchar(10),
phone varchar(11),
c_id int,
foreign key(c_id) references customer(id)
on delete cascade
on update cascade
);
mysql> desc customer;
+-------+-------------+------+-----+---------+----------------+
| 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 detail;
+--------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| gender | varchar(10) | YES | | NULL | |
| phone | varchar(11) | YES | | NULL | |
| c_id | int(11) | YES | MUL | NULL | |
+--------+-------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)