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