MySQL表的约束和表的增删查改
Posted 两片空白
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL表的约束和表的增删查改相关的知识,希望对你有一定的参考价值。
目录
一.表的约束
mysql管理用户数据的软件,需要严格的保证数据的正确性和安全性。于是,MySQL对用户输入的数据增加了许多约束。比如:数据的类型,当数据超过类型的最大长度,会直接报错。但是,只有类型进行约束是很单一的。MySQL还增加了很多额外的约束,下面介绍。
MySQL表的约束,倒逼着用户输入数据时,必须数据正确的数据。约束条件越严格,数据越精确越安全。
1.1 空属性
- 两个值:null(空,默认)和not null(不为空)
- 作用:null约束表中字段可以设为空,not null约束表中字段不可设为空。
案例:
插入数据插入空时会失败:
1.2 默认值
默认值:当用户将一字段设定默认值,当用户插入数据时,不插入值,会使用默认值。
当对设置默认值的字段不插入值时,会使用默认值:
注意:如果没有设定默认值,并且不能为空,插入时,必须插入值。
default和not null一般不需要同时约束一个字段,应为本身会有默认值。
1.3 列描述
列描述:comment:用来描述当前字段的含义。
1.4 zerofill
- 作用:可以显示字段的长度。
总结一下:zerofill是一种格式化输出,当长度小于设置长度,剩余长度填充0。虽然填充了0,实际值并没有发生改变。
1.5 主键
- 语法:用primary key修饰字段。
- 作用:该字段里的数据不能有重复,不能为空,一张表中最多只有一个主键;主键修饰的字段一般是整数类型。
案例:
- 创建表,其中字段用约束为主键
- 插入数据
- 当表创建好,但是忘记设置主键约束,可以再次追加主键约束条件。
alter table 表名 add primary key (字段名称);
- 删除主键
alter table 表名 drop primary key;//不需要加字段名称,因为一个表中只有一个主键。
- 复合主键
当一个表中想设置多个字段为主键,可以使用复合主键。
语法:在创建表示,增加primary key(主键字段列表)。
一个表中只能有一个主键,为什么这里可以出现多个主键呢?
这里的多个主键实际上也只是一个主键,需要所有主键字段组合才真正构成主键。意思就是,需要两个都一样才会构成冲突。但是,两个主键都不能设置为空。
1.6 自增长
语法:创建表时,用auto_increment修饰字段。
功能:不给值时,系统会自动触发,会进行从当前字段中已经有的最大值加1操作。
通常和主键搭配使用,作为逻辑主键。
特点:
- 任何字段要做自增长,前提本身时索引(key一栏有值)。
- 自增长字段必须是整数。
- 一张表最多只能有一个自增长。
案例:
- 插入数据:
- 修改自增初始值
一种方式:创建时修改初始值
一种方式,在第一次插入时,设置自增字段的值。
- 查询上一次自增值。
1.7 唯一键
语法:在字段约束加上unique。
作用:唯一键修饰的字段不能有重复数据。
表中往往有很多字段需要唯一性,数据不能重复。但是一张表中只有一个主键,唯一键解决了有多个字段需要唯一性的约束问题。
唯一键和主键功能相似,它们的区别在于:
- 唯一键可以有多个。
- 唯一键可以一个或者多个为空。
- 唯一键不需要全部唯一键和已经插入值一样才冲突。
- 主键主要是用在与业务无关的字段,避免因为业务改变主键也需要改变
- 唯一键主要是用在与业务相关的字段。
1.8 外键
一种情况,现实生活中,一种场景下,可能需要记录的数据会很多。如果将其记录在一张表中,会导致一张表的数据量很大,并且用户看起来麻烦。我们可以将数据拆除成多个表,使用一个字段,使表与表之间产生联系。
使一张表和另外一张表产生联系的字段为外键。含有外键的表叫从表,不含有外键的表叫主表。
外键的约束是,为了保证两个表信息一致。如果删除某个表的信息时,可能另外一个表中还保存着删除字段的信息,导致信息不一致,这时会报错。必须键要删除的信息全部删除。
删除信息时,需要先删除从表中需要删除的数据,再来删除主表中的数据。
语法:foreign key (字段名) references 主表列;
作用:使两张表产生联系。
外键用来定义主表和从表之间的关系,外键约束主要定义在从表上,主表必须是有主键约束或者unique约束。当定义外键后,要求外键列数据必须在主表的主键列存在或者为空。
- 正常插入数据
- 如果插入不在主表的id数据中:会导致两个表数据不一致。
- 但是可以插入空值
- 删除主表某一字段
先删除从表中字段含有的信息,才能删除主表的字段。
如何理解外键约束:
上面的例子,如果我们不建立外键约束。我们也可以正常创建这两个表,但是两个表的联系需要我们用户来注意。
比如:删除一个班级,需要将班级里的所有学生信息都要删除。如果用户疏忽,导致忘记删除或者将学生信息插入到了一个不在班级表中的班级,这样就会出现问题。需要用户自己注意这样成本是很高的。
于是将这种联系的审核交给了MySQL。当我们错误插入,或者未将数据删除干净时,MySQL会提醒我们,约束我们必须做出正确的操作。
二.表的增删查改
CRUD:Create(创建),Retrieve(读取),Update(更新),Delete(删除)。
2.1 Create(创建)
在表种插入字段。
语法:insert into 表名 (字段) values (字段具体值)
案例:
创建一张表:
- 单行数据,全部插入
- 多行数据,指定列插入
注意:前面的字段和后面的数据必须顺序一致。
- 插入,否则更新
由于主键或者唯一键对应的值已经存在,导致插入失败。
如果插入失败,可以选择进行更新,如果插入成功直接插入。
语法:insert into 表名 (字段) values (字段具体值) on duplicate key update (具体更新字段)
通过MySQL函数获取受影响的数据行数。
- 替换
主键或者唯一键没有冲突,直接插入。
主键或者唯一键冲突,则删除后插入。
语法: replace into 表名 (字段) values (字段对应具体数据)
2.2 Retrieve(读取)
语法:
SELECT [DISTINCT] * | column [, column] ... [FROM table_name] [WHERE ...] [ORDER BY column [ASC | DESC], ...] LIMIT ...
案例:
创建一个表,并且插入数据:
2.2.1 全列查询
- 一般不建议使用全列查询
- 查询的列越多,MySQL是网络服务,意味着传输的数据量越大。
- 可能会影响到索引的使用。
2.2.2 指定列查询
执行列的顺序不需要按照创建表的顺序输入。
2.2.3 查询字段为自定义表达式
- 表达式不包含表中的字段
- 表达式中包含一个字段
- 表达式包含多个字段
注意:自定义表达式并没有修改表,只是修改显示的值。
2.2.4 为查询结果指定别名
语法:select 字段名 as(可省略) 别名 from 表名;
2.2.5 对查询结果去重
2.2.6 where 条件
比较运算符:
逻辑运算符:
案例:
//英语不及格的同学及英语成绩 (<60)
select name,english from exam_result where english < 60;
//语文成绩在 [80, 90] 分的同学及语文成绩
//用逻辑and
select name, chinese from exam_result where chinese>=80 and chinese<=90;
//用between...and...
select name, chinese from exam_result where chinese between 80 and 90;
//数学成绩是 58 或者 59 或者 98 或者 99 分的同学及数学成绩
//用or连接
select name, math from exam_result where math=58 or math=59 or math=98 or math=99;
//用in
select name, math from exam_result where math in (58,59,98,99);
// 姓孙的同学
select name from exam_result where name like '孙%';
//查询孙某同学
select name from exam_result where name like '孙_';
//语文成绩好于英语成绩的同学
select name, chinese, english from exam_result where chinese > english;
// 总分在 200 分以下的同学
select name, chinese+english+math '总分' from exam_result where chinese+english+math < 200;
注意别名不能出现在where中:
//语文成绩 > 80 并且不姓孙的同学
select name, chinese from exam_result where chinese > 80 and name not like '孙%';
// 孙某同学,否则要求总成绩 > 200 并且 语文成绩 < 数学成绩 并且 英语成绩 > 80
select name, chinese+english+math '总分', chinese, math, english from exam_result where name like '孙_' or
(chinese+english+math > 200 and chinese<math and english>80);
- null 查询
//查询qq为null
select * from students where qq is null;
//查询qq不为空
select * from students where qq is not null;
- null和null比较
'='不起作用,比出来都是空。
'<=>'起作用
2.2.7 排序
语法:select... from 表名 [WHERE ...] order by 字段 [ASC|DESC], [...];
ASC:升序。从小到大
DESC:降序。从大到小
注意:没有order by的子句查询,返回的顺序都是未定义的。
注意:字段数据为空,比任何值都小。
//同学及数学成绩,按数学成绩升序显示
select name, math from exam_result order by math;//默认升序
select name, math from exam_result order by math asc;
//查询同学各门成绩,依次按 数学降序,英语升序,语文升序的方式显示
select name, math, chinese, english from exam_result order by math desc, english, chinese;
// 查询同学及总分,由高到低
select name, chinese+english+math from exam_result order by chinese+english+math desc;
//可以使用别名
select name, chinese+english+math '总分' from exam_result order by 总分 desc;
//查询姓孙的同学或者姓曹的同学数学成绩,结果按数学成绩由高到低显示
//可以使用where的结果来进行排序
select name, math from exam_result where name like '曹%' or name like '孙%' order by math desc;
2.2.8 筛选分页结果
语法:
从0,开始筛选n条结果
select ... from 表名 [where ...] [order by ...] limit n
从s位置开始,筛选出n条结果
select ... from 表名 [where ...] [order by ...] limit s ,n
从s位置开始,筛选出n条结果,比第二种更加明确
select ... from 表名 [where ...] [order by ...] limit n offset s
建议:对位置表进行查询时,最好加一条limit 1,避免表中数据过大,查询全表数据导致数据库卡死。
案例:
按id进行分页,每页3条记录,分别显示第1,2,3页。
2.3 Update(更新)
语法:update 表名 set 字段=更新数据 [where ...] [order by...] [limit ...]
对查询的结果进行更新。
- 修改单个数据
- 修改多个数据
将总成绩倒数前三的 3 位同学的数学成绩加上 30 分
将所有同学的语文成绩更新为原来的 2 倍
2.4 Delete(删除)
语法:delete from 表名 [where...] [order by...] [limit...]
2.4.1 删除数据
删除孙悟空的考试成绩
删除整张表的数据
删除整张表,只是删除了表中的数据,表结构依然存在。
查看表结构中,auto_increment项更新为n。
2.4.2 截断表
语法:truncate [table] 表名;
作用:删除表的数据。
注意:这个操作慎用。
- 只能对整个表进行操作,不能像delete对部分数据操作。
- 会重置表结构的auto_increment选项。
- 实际上截断,MySQL不会对数据操作,所以会比delete快。但是truncate在删除数据时,并不经过真正的事务,所以无法回滚。
回滚:将删除的数据恢复的操作。
实际上,当我们通过MySQL对数据进行操作时,MySQL的日志中会记录与你相反的操作,防止误操作,可以进行数据恢复。
比如:你使用delete删除一条数据,在MySQL日志记录为insert插入一条数据。
而truncate不会在日志中有记录。所以无法回滚。
2.5 插入查询结果
语法:insert into 表名 字段 select ...
案例:将一张表中的数据去重插入到另外一张数据中。
修改表名:
2.6 聚合函数
函数 | 说明 |
count([distinct] 表名) | 返回查询到数据的数量 |
sum([distinct] 表名) | 返回查询到数据的总和,不是数字没有意义 |
avg([distinct] 表名) | 返回查询到数据的平均数,不是数字没有意义 |
max([distinct] 表名) | 返回查询到数据的最大值,不是数字没有意义 |
min([distinct] 表名) | 返回查询到数据的最小值,不是数字没有意义 |
案例:
对于表:
测试count:
- 使用'*'做统计,为记录数据的个数
注意空不会记录进结果
- 统计数据成绩分数的个数,去重和未去重。
- 统计数学总分
- 总分平均分
- 统计英语最高分
- 返回 > 70 分以上的数学最低分
2.7 group by子句使用
在select使用group by进行分组查询。
在公司中有很多部门,select只能事项全部部门的查询,加上group by可以实现不同部门之间的查询。
语法:select ... from 表名 group by 分组字段;
案例:
- 准备工作,创建一个雇员信息表(来自oracle 9i的经典测试表)
- EMP员工表
- DEPT部门表
- SALGRADE工资等级表
- 显示每一个部门的平均工资和最高工资
如果不加group by计算的就是所有的,就看不出部门之间的区别。
- 显示每个部门的每种岗位的平均工资和最低工资
- 显示平均工资低于2000的部门和它的平均工资
显示部门和平均工资,条件平均工资低于2000
having和group by配合使用,对group by结果进行过滤
以上是关于MySQL表的约束和表的增删查改的主要内容,如果未能解决你的问题,请参考以下文章