1. 约束概念
表中一定要有各种约束,通过约束,让未来插入数据库表中的数据是符合预期的
约束本质是 通过技术手段,倒逼程序员 插入正确的数据
站在mysql的视角,凡是插入进来都是符合数据约束的
约束的最终目标:保证 数据的完整性和可预期性
如:使用VS时,当代码写错了,编译器就会报错,如果不改错而执行代码,就会导致执行不通过
必须将错误修改正确,才能执行才能通过
2. 空属性
在mysql中 NULL表示没有
’ ’ 表示空串,有只不过是空的
输入 select NULL; 查询时发现什么都没有
共有两种默认值:null (默认为空) 和 not null(不为空)
数据库默认字段基本都是字段为空,但是实际开发时,尽可能保证字段不为空,因为数据为空没办法参与计算
创建一个班级表,内部包含 一个 班级名称和 教室名称 以及其他
其中班级名称和班级教室都不能为空,所以设置 not null 进行约束
而其他没有约束,也就没有带 not null
输入 desc myclass; 查看myclass 表的更详细信息
Null 表示对应 列未来做插入时,是否为空
如: class_name 这一列未来做插入时 不能为空
other 这一列 未来做插入时,可以为空
向myclass表中 插入 班级名 初一6班, 班级教室 111教室,其他为普通班 时,是可以成功插入的
再次插入时,没有给other具体的值,此时依旧可以插入成功
当查看表 的信息时,other为NULL
(other没有添加非空约束)
当插入班级名称 以及 教室名称设置为空时,就会插入失败
(因为class_room 添加了非空约束)
3. 默认值
某一种数据会经常性的出现某个具体的值,可以在一开始就指定好,在需要真实数据的时候,用户可以选择性的使用默认值
创建一张表t11 ,内部包含 不能为空的名字 、 默认值为18 的年龄、 默认为男的性别
当插入 名字为张三、年龄为19、性别为女,可以插入成功
当只插入名字李四时,也是可以插入成功的
显示表的信息时,年龄和性别都为默认值
所以 deault 如果设置了,用户将来插入,有具体的数据了,就用用户的,没有就用默认的
创建一张表 t12,内部包含 不能为空的名字、 默认为18的年龄、 不能为空且默认为男的性别
性别 把 deault 和not null 同时设置了
若向t11表中插入年龄和性别,而不插入名字
就会报错,没有默认值存在
结论: 若没有明确指定一列要插入,用的是default
如果建表中对应的列默认没有default值,就无法直接插入
向t11表中只插入名字和年龄,不插入性别
由于性别有默认值存在,所以会使用默认值
所以查询表信息时,发现赵六的性别为默认值男
如果忽略某一列,若设定了默认值且默认值不为空,则可以直接插入
default 作用于 当用户忽略这一列时,如果设置了默认值,则使用默认值
not null 作用于 当用户想插入时,若输入null 则会报错 ,约束用户输入合法数据
5. ***ment——列描述
***ment 后面跟的相当于注释
创建一张表 t13,内部包含 用户名 、默认为男的用户性别
输入 show create table t13 \G 获取t13表更详细信息
就可以看到列信息的描述字段
6. zerofill
创建一张表 t14,内部包含 一个 无符号的整形 a 与 无符号的整形 b
两者都不能为空
输入 show create table t14 \G 查询t14表中更详细的信息
发现 默认 mysql 的int 带了一个10
无符号范围为0 到42亿多,所以需要宽度10去表示
所以 无符号int 的默认宽度为10
向t14表中插入 1 和 2,
输入 select *from t14; 查看t14表结构
目前来看没有什么问题
将t14表中的b成员类型改为 无符号int 并添加 向zerofill
再次输入 select *from t14; 查看t14表的结构
a没有变化,而b从 2变成 0000000002
zerofill的作用为 给特定的一列添加 zerofill属性
对于结果,如果显示的宽度 少于 限定的宽度,则会自动填0
如:int类型的限定宽度为10,则输入的2 显示宽度为1,就默认在2前面全部补充0 ,就把 2变为 0000000002
将t14表中的b成员类型改为 int的限定宽度为3
分别插入 1 20 和 1 2000
可以发现 当小于限定宽度时,会在前面自动填充0
如:20 显示宽度为2 ,小于限定宽度 3 ,所以在前面填充0
而大于限定宽度时,就什么都不做
如:2000 显示宽度为4,大于限定宽度3,就直接显示
7. 主键
primary key 用来唯一的约束该字段里面的数据,不能重复,不能为空,一张表最多只有一个主键
主键所在的列 通常是整数类型
创建一张表 test_key,内部包含 被设置为主键的学号 以及 不能设置为空的 名字
学号id中并没有设置为非空,但是查询test_key表结构时,发现自动将其设置为 not null
由于学号被设置为主键
所以查询时 在key 列(表示当前列是否为主键列),发现id所在列为 PRI (当前为主键列)
将 id为1,名字为刘备 插入到test_key表中,可以插入成功
当再次在相同的id中,插入不同的名字时,就会报错,出现 主键冲突
所以就需要去其他的id中去插入
主键约束:如果想要在一个表中插入,主键是不可以冲突的,如果冲突 就会插入失败
输入 alter table test_key drop primart key; 将 主键从test_key表中删除
输入 desc test_key; 发现当前的test_key表中不存在主键
再次输入 insert into test_key values(1,‘张飞’); 向test_key表中插入 1 张飞 ,是可以插入成功的(没有主键约束)
也可以将表建好后,再添加主键
当前的test_key 表是没有主键存在的
输入 alter table test_key add primary key(id);
向 test_key表中的id成员插入 主键
但是会报错,因为 当前test_key表中存在主键冲突
必须将其解决,才能添加主键
输入 delete from test_key where name=‘张飞’; 即可删除test_key表中的张飞信息
再次输入 alter table test_key add primary key(id); 即可再test_key表中加入主键
8. 复合主键
虽然一个表中只能有一个主键,但是并不意味着一个表中的主键,只能添加给一列
即 一个主键 也可以被添加到多列 ——复合主键
创建一张表 pick_course,内部包含 无符号int的id、课程编号、课程分数
为了使 学生 与课程编号 是一对一的关系,所以将 id 和course_id 都包含 主键
输入 desc pick_course; 查看pick_course表结构
id和course_id中都包含同一个主键
第一次插入 1200 50 90 ,可以插入成功
第二次插入 1300 50 80, 也可以插入成功
因为 id与course_id是一对一关系,即只是不能有相同的id与course_id存在
再次插入 1200 50 40 ,因为与第一次插入 1200 50 重复了
引起 主键冲突,就会报错
9. 自增长
auto_increment :当对应的字段 不给值,会自动的被系统触发,系统会从当前字段中已经有的最大值+1操作,得到一个新的不同的值,通常和主键搭配使用,作为逻辑主键
自增长的特点:
任何一个字段要自增长,前提key一栏要有值
自增长字段必须是整数
一张表最多只能有一个自增长
加入 auto_increment ,表示当前这一列属于自增式主键
创建一张表 tt21,内部包含 自增式主键 的id 以及 不能为空的名字
输入 desc tt21; 查看tt21表结构
key列的PRI 表示 id为主键列
Extra列的auto_increment 表示 id列是自增的
分别只插入 名字 a和 名字 b
输入 select * from tt21; 查看tt21表结构,发现id会从1开始 并加1(保证跟别人不冲突,并且是连续的)
若想自定义id进行插入 ,也是可以的
并且当再次插入相同id时,就会引起主键冲突,从而插入失败
当前面id为500时,再次插入数据,就会id就会默认从501开始
创建表 tt23,并在表外设置id的默认值从400开始
只插入名字e时,id就会默认从400开始
10. 唯一键
一张表中有很多字段需要唯一性,数据不能重复,但是一张表中只能有一个主键
唯一键就可以解决表中多个字段需要唯一约束的问题
唯一键和主键差不多,唯一键允许为空,而且可以多个为空,空字段不做唯一性比较
使用 unique 创建唯一键
(写成 unique 或者 unique key 都可以)
创建一张表 stu ,内部包含 拥有唯一键的id 以及 不为空的名字
输入 desc stu; 查看stu表结构
发现 key列 内部 变为 UNI
第一次插入 id为1234,名字为李四,插入成功
第二次插入与第一次插入的id相同,就导致 唯一键 冲突,从而插入失败
若插入id为空,虽然名字相同,但依旧可以插入成功
若连续插入 NULL 值,皆可插入成功
唯一键表达了类似于主键的功能
但是唯一键可以为空,并且空值可以多次插入(NULL不参与计算)
而主键不可以为空
关于唯一键的理解
创建一张表student, 内部包含 id 、名字、电话
将成员id设置为主键
将id为1234、名字为张三、电话为123456 插入到student表中,并插入成功
若将id修改与名字修改 而电话不变,将其插入到student表中
张三和李四的电话号相同
但是正常情况下是不存在,因为每一个人的电话号是唯一的
当想要通过电话号去寻找对应的人时,就发现无法准确找到对应的人
所以在主键保证唯一性的同时,其他字段有可能也需要唯一性,此时就需要借助唯一键来实现
重新创建 表student,内部包含 主键的id、不为空的名字、唯一键的电话号、唯一键的qq号
输入 desc student; 查看student表结构
为了保证电话号和qq号的唯一性,所以两者包含唯一键
当将 id为1234、名字为李四、电话号为123456、qq号为456789 成功插入时
再次插入id 相同的人时,就会因为 主键冲突 而插入失败
当将 id为1234、名字为李四、电话号为123456、qq号为456789 成功插入时
再次插入 电话号与qq号 相同的人时,就会因为 唯一键冲突 而插入失败
11. 外键
外键用于主表和从表之间的关系,外键约束主要定义在从表上,主表则必须是有主键约束或者unique约束(唯一键约束)
当定义外键后,要求外键列数据必须在主表的主键列存在或为null
语法:
foregin key(字段名) references 主表(列)
外键的理解
创建一张学生表student,包含 主键且自增长的id 、不为空的名字、不为空的电话号、班级号
(正常来说 电话号 是唯一的,应该加上唯一键,这里只是初步测验,所以没有加)
输入 desc student; 查看student表结构
再创建一个班级表class,内部包含 主键的id、不为空的名字
向class表中 插入 班级1 通信101 ,以及 班级2 通 信102
向student表中第一次插入 名字为张三、电话为123456、1号班级
由于id拥有主键并且为自增长的,所以默认从1开始,每次加1
第二次插入 名字为李四、电话为456789、2号班级
由于张三是1号班级的,所以查找1号班级,发现通信101
假设 向student表中 误插入3号班级中
逻辑上存在有一个学生所属的班级 并不存在
若:王五属于3号班级,但是class表中只有1号和2号班级
MySQL数据库就要通过数据手段在逻辑上规避 并不符合要求的情况的产生
输入 delete from class where d=1; 将 class表中 id值为1 删除
此时再次查看 class表,发现 只剩下 id值为2
但是这种删除不合理 因为在student表 还有 属于1号班级的信息 存在
这样就会导致每次操作前 ,就需要查看是否影响其他表中的信息
班级表可以看作是主表,学生表可以看作 从表
外键需要考虑两层面的关系:关联关系 和 约束关系
student表中的class_id 有关联关系,但是没有约束关系
若要插入一名学生,但是插入的班级并不存在,就不允许插入,使其插入一个合法的id
为了创建出主表和从表的关系,就需要使用 外键 重新创建从表
先输入 drop table student; 将从表 student 去掉
再次创建从表 student,内部包含 主键的id、不为空的name、唯一键的telphone、class_id
并使 student表中的 class_id作为外键,与 class表中的id 产生外键约束
输入 desc stud***; 查看student表的结构
class_id对应的 default列中的 MUL 表示 外键约束
输入 desc class ; 查看class表的结构
发现有id值为1的通信101 和id值为2的通信102
第一次插入 id值为100 、名字为张三、电话为1234、班级号为1
第二次插入 id值为101、名字为李四、电话为4567 、班级号为2
两者都插入成
输入 select * from student; 查看student表的结构
当插入到 3号班级时,因为 class表中只有1号班级和2号班级 ,并不存在3号班级,所以就会发生外键约束
同样若想删除 class 主表中的id值为1的班级 是不可以的,因为id值为1的班级在 student 从表中存在信息
外键约束 保证 表跟表之间数据做删除时的逻辑关系 和数据的完整性
先将student从表中的id值为100 1号班级的信息 删除
再次 就可以删除掉 class表中的 1号班级了
想要使用外键 ,就需要先保证 从表和主表的关联关系(学生表 和班级表)
再 产生外键约束 (不会在学生表中插入一个不存在班级的学生,也不会在删除 在学生表中有信息的 班级)