字段约束条件、外键建立数据关系
unsignedid int unsignedzerofillid int(5) zerofill
create table t1(id int, name varchar(16));insert into t1(id) values(1);insert into t1(name) values('jason');insert into t1(name,id) values('kevin',2);
加上限制条件之后:
create table t2(id int, name varchar(16) not null);insert into t2(id) values(1);
# ERROR 1364 (HY000): Field 'name' doesn't have a default valueinsert into t2(name) values('alex');
# Query OK, 1 row affected (0.00 sec)insert into t2 values(1,'');
# Query OK, 1 row affected (0.00 sec)insert into t2 values(2,null);
# ERROR 1048 (23000): Column 'name' cannot be null
当限制了name为非空的时候,如果name不输入或者输入为null时,都会报错,没法成功添加
注意: 当name输入为' '时,是不会报错的,添加进去的name就是空.
create table t3(id int default 666,name varchar(16) default '匿名');insert into t3(id) values(1);insert into t3(name) values('alex');insert into t3 values(2,'kevin');
可以看到,当我们不输入时, id或name就会显示我们输入的默认值.
unique)
单列唯一
create table t4(id int unique,name varchar(32) unique);insert into t4 values(1,'alex'),(2,'alex');
# ERROR 1062 (23000): Duplicate entry 'alex' for key 'name'
当id和name设置为unique时, 输入两个相同的name,就会报错.
2. 联合唯一
create table t5(id int, ip varchar(32), port int, unique(ip,port));insert into t5 values(1,'127.0.0.1',8080),(2,'127.0.0.1',8081),(3,'127.0.0.2',8080);
# Query OK, 3 rows affected (0.00 sec)insert into t5 values(4,'127.0.0.1',8080);
# ERROR 1062 (23000): Duplicate entry '127.0.0.1-8000' for key 'ip'
ip和port放在一个元组里面,设置为联合唯一, 当ip或port只有一个相同时是可以正常插入的, 当两个都相同时会报错,没法插入.
primary key)
create table t6(id int primary key,name varchar(32));insert into t6(name) values('jason');
# ERROR 1364 (HY000): Field 'id' doesn't have a default valueinsert into t6 values(1,'kevin');
# Query OK, 1 row affected (0.00 sec)insert into t6 values(1,'jerry');
# ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'
id设置为主键,当不输入id时,会报错;当输入重复的id时,也会报错.
InnoDB存储引擎规定了所有的表都必须有且只有一个主键(主键是组织数据的重要条件并且主键可以加快数据的查询速度)
- 1. 当表中没有主键也没有其他非空且唯一的字段的情况下,InnoDB会采用一个隐藏的字段作为表的主键, 隐藏意味着无法使用, 基于该表的数据查询只能一行行查找, 速度很慢
- 2. 当表中没有主键但是有其他非空且唯一的字段, 那么会从上往下将第一个该字段自动升级为主键
create table t7(id int,age int not null unique,phone bigint not null unique,birth int not null unique,height int not null unique);
说明:
我们在创建表的时候应该有一个字段用来标识数据的唯一性, 并且该字段通常情况下就是'id'(编号)字段
id nid sid pid gid uid
create table userinfo(uid int primary key);
create table t8(id int primary key,name varchar(32));insert into t8 values(1,'alex');insert into t8 values(2,'kevin');
当仅仅只是设置主键时,需要我们自己手动输入编号.
加上auto_increment条件之后, 编号会自动增加.
create table t9(id int primary key auto_increment,name varchar(32));insert into t9(name) values('alex');insert into t9(name) values('kevin');
但是自增存在一个问题, 自增不会因为数据的删除而回退,永远自增往前
如果自己设置了更大的数, 则之后按照更大的往前自增.
如果自己设置了更大的数, 则之后按照更大的往前自增.
如果删除掉所有的数据, 重新再插入数据时, id值还是接着之前的往上自增.
如果想重置某张表的主键值, 可以使用truncate t9; 清空表数据并重置主键, 但是id值还是接着之前的往上自增.
上述员工表中存在的问题:
1.表语义不明确(到底是员工还是部门) 无所谓
2.存取数据过于冗余(浪费存储空间) 无所谓
3.数据的扩展性极差 不能忽略
有没有什么方法可以一次解决上述三个问题?
将上述表一分为二:
上述的三个问题全部解决, 但是员工跟部门之间没有了关系.
我们可以给每个员工绑定部门编号:
根据相应的编号即可查找员工的部门信息, 这个编号字段我们叫做外键字段.
外键字段: 用于标识数据与数据之间关系的字段
表关系、数据关系其实意思是一样的, 只是说法上有区分.
关系总共有四种
- 一对多
- 多对多
- 一对一
- 没有关系
关系的判断可以采用'换位思考'原则.
以员工表和部门表为例1.先站在员工表的角度 问:一名员工能否对应多个部门 答:不可以 2.再站在部门表的角度问:一个部门能否对应多名员工答:可以结论:一个可以一个不可以, 那么关系就是'一对多'
针对'一对多'关系, 外键字段建在'多'的一方
注意:
1.创建表的时候一定要先创建被关联表, 否则会报错
- 关联表:有foreign字段的表
- 被关联表:被关联表绑定的表
# 被关联表create table dep(id int primary key auto_increment,dep_name varchar(32),dep_desc varchar(64));# 关联表create table emp(id int primary key auto_increment,name varchar(32),age int,dep_id int,foreign key(dep_id) references dep(id));
2.录入表数据的时候一定要先录入被关联表
insert into dep(dep_name, dep_desc) values('讲师部','教书育人'),('安保部','保卫国土'),('财务部','发工资');# 注意符号都得是英文格式
再录入关联表:
insert into emp(name,age,dep_id) values('jason',18,1),('kevin',28,2),('tony',56,2),('oscar',35,3),('jerry',34,3);
3.修改数据的时候, 外键字段无法修改和删除
delete from dep where id=1;# ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`db3`.`emp`, CONSTRAINT `emp_ibfk_1` FOREIGN KEY (`dep_id`) REFERENCES `dep` (`id`))
针对3有简化措施>>>:级联更新级联删除
create table dep1(id int primary key auto_increment,dep_name varchar(32),dep_desc varchar(64));create table emp1(id int primary key auto_increment,name varchar(32),age int,dep_id int,foreign key(dep_id) references dep1(id) on update cascade on delete cascade);
更改被关联表中的信息:
外键其实是强耦合, 不符合解耦合的特性
所以很多时候, 实际项目中当表较多的情况, 我们可能不会使用外键, 而是使用代码建立逻辑层面的关系
以书籍表与作者表为例
1.先站在书籍表的角度 问:一本书能否对应多个作者 答:可以 2.再站在作者表的角度问:一个作者能否对应多本书答:可以 结论:两个都可以 关系就是'多对多'
针对'多对多'不能在表中直接创建, 需要新建第三张关系表
create table book(id int primary key auto_increment,title varchar(32),price float(5,2));create table author(id int primary key auto_increment,name varchar(32),phone bigint);create table book2author(id int primary key auto_increment,author_id int,foreign key(author_id) references author(id)on update cascadeon delete cascade,book_id int,foreign key(book_id) references book(id)on update cascadeon delete cascade);
1.先站在用户表的角度 问:一个用户能否对应多个用户详情 答:不可以 2.再站在用户详情表的角度 问:一个用户详情能否对应多个用户 答:不可以结论:两个都可以 关系就是'一对一'或者没有关系
针对'一对一'外键字段建在任何一方都可以, 但是推荐建在查询频率较高的表中
create table userdetail(id int primary key auto_increment, phone bigint);create table user(id int primary key auto_increment, name varchar(32), detail_id int unique, foreign key(detail_id) references userdetail(id) on update cascade on delete cascade);
注: 一对一的关系, 必须把外键字段设置为唯一
作者:莫~慌
来源链接:https://www.cnblogs.com/chen-ao666/p/16922083.html
版权声明:
1、JavaClub(https://www.javaclub.cn)以学习交流为目的,由作者投稿、网友推荐和小编整理收藏优秀的IT技术及相关内容,包括但不限于文字、图片、音频、视频、软件、程序等,其均来自互联网,本站不享有版权,版权归原作者所有。
2、本站提供的内容仅用于个人学习、研究或欣赏,以及其他非商业性或非盈利性用途,但同时应遵守著作权法及其他相关法律的规定,不得侵犯相关权利人及本网站的合法权利。
3、本网站内容原作者如不愿意在本网站刊登内容,请及时通知本站(javaclubcn@163.com),我们将第一时间核实后及时予以删除。