批量插入:是一种优化数据逐条插入的方式
批量插入数据的语法与简单数据插入的语法差不多
批量插入分为两种:
insert into 表名 values(值列表1),(值列表2),...(值列表N);
insert into 表名 (字段列表) values (值列表1),(值列表2),...(值列表N);
批量插入可以针对性解决数据的批量导入之类的业务,可以一次性解决多条数据插入,能够有效降低客户端占用问题,提升数据操作效率
示例
1、批量插入学生成绩(t_1全字段)
insert into t_1 values(null,'Tom','Computer',90),(null,'Lily','Computer',92);
2、批量插入学生考试信息(t_1不包含成绩)
insert into t_1 (stu_name,course) values('Tony','English'),('Ray','Math');
蠕虫复制:从已有表中复制数据直接插入到另外一张表(同一张表)
蠕虫复制的目标是快速增加表中的数据
蠕虫复制语法:insert into 表名 [(字段列表)] select 字段列表 from 表名;
注意事项:
示例
1、创建一张新表,将t_1表中的数据迁移到新表t_2中
create table t_1(
id int primary key auto_increment,
stu_name varchar(20) not null,
course varchar(20) not null,
score decimal(5,2)
)charset utf8;
insert into t_2 select * from t_1;
2、快速让t_2表中的数据增长(重复执行)
insert into t_2 (stu_name,course,score) select stu_name,course,score from t_2;
主键冲突:在数据进行插入时包含主键指定,而主键在数据表已经存在
主键冲突的业务通常是发生在业务主键上(业务主键本身有业务意义)
主键冲突的解决方案:
insert ignore into 表名 [(字段列表)] values(值列表);
insert into 表名 [(字段列表)] values(值列表) on duplicate key update 字段 = 新值[,字段=新值...];
replace into 表名 [(字段列表)] values(值列表); # 效率没有insert高(需要检查是否冲突)
从效率上来讲,insert into
不考虑冲突的效率最高,三种解决冲突的方式都会有效率下降(需要检索),其中三种本身的效率依次是:忽略新数据 > 更新部分数据 > 替换全部
示例
1、用户名作为主键的用户注册(冲突不能覆盖):username,password,regtime
create table t_3(
username varchar(50) primary key,
password char(32) not null,
regtime int unsigned not null
)charset utf8;
insert into t_3 values('username','password',12345678);
# 冲突忽略
insert ignore into t_3 values('username','12345678',12345678);
2、用户名作为主键的记录用户使用信息(不存在新增、存在则更新时间):username,logintime
create table t_4(
username varchar(50) primary key,
logintime int unsigned
)charset utf8;
insert into t_4 values('username',12345678); # 当前时间戳
# 冲突更新(替换部分字段数据)
insert into t_4 values('username',12345678) on duplicate key update logintime = unix_timestamp(); # 当前时间戳
3、用户名作为主键的记录用户使用信息(不存在新增、存在则更新全部):username,logintime、clientinfo
create table t_5(
username varchar(50) primary key,
logintime int unsigned,
clientinfo varchar(255) not null
)charset utf8;
insert into t_5 values('username',unix_timestamp(),'{PC:chrome}');
# 替换插入
replace into t_5 values('username',unix_timestamp(),'{phone:uc}');
查询选项:用于对查询结果进行简单数据筛选
示例
1、查看商品表中所有品类的商品信息:重复的商品只保留一次(名字、价格、属性都一致)
create table t_6(
id int primary key auto_increment,
goods_name varchar(50) not null,
goods_price decimal(10,2) default 0.00,
goods_color varchar(20),
goods_weight int unsigned comment '重量,单位克'
)charset utf8;
insert into t_6 values(null,'mate10',5499.00,'blue',320),
(null,'mate10',5499.00,'gray',320),
(null,'nokia3301',1299,'black',420);
# 考虑所有字段的去重(不含逻辑主键)
select distinct goods_name,goods_price,goods_color,goods_weight from t_6;
select goods_name,goods_price,goods_color,goods_weight from t_6; # 保留所有
# 不考虑颜色去重
select distinct goods_name,goods_price,goods_weight from t_6;
select all goods_name,goods_price,goods_weight from t_6;
字段选择:根据实际需求选择的要获取数据的字段信息
根据实际需求,明确所需要的字段名字,使用英文逗号,
分隔
获取所有字段,使用星号*
通配所有字段
字段数据可以不一定是来自数据源(select只要有结果即可)
select 1
select unix_timestamp(),@@version
(@@是系统变量的前缀,后面跟变量名)字段的选择只要在保证数据需求能实现的情况下,尽可能少使用*
代替(MySQL优化)
字段别名:给字段取的临时名字
字段名 as 别名
字段名 别名
示例
1、查询商品信息
# 全部查询
select * from t_6;
# 需求为商品名字和价格
select goods_name,goods_price from t_6;
# 别名使用
select goods_name as gn,goods_price gp from t_6;
2、不需要数据源的数据获取:select的表达式本身能算出结果)
# 获取当前时间戳和版本号
select unix_timestamp() as now,@@version as version,@@version;
数据源:from关键字之后,数据的来源。只要最终结果是一个二维表,都可以当做数据源
单表数据源:数据源就是一张表 from 表名
多表数据源:数据来源是多张表(逗号分隔) from 表名1,表名2,...表名N
子查询数据源:数据来源是一个查询结果 from (select 字段列表 from 表名) as 别名
数据表也可以指定别名
表名 as 别名
表名 别名
数据源是为查询、检索提供数据支持的,使用时需要明确指定
通常情况下数据源不会使用简单的多表数据源(笛卡尔积)
数据表的别名在负责SQL查询操作时非常有用,而且有些地方是必须使用(如子查询数据源)
示例
1、单表数据源:最简单的数据源,直接从一个数据表获取
select * from t_7;
2、多表数据源:利用一张表的一条数据匹配另外一张表的所有记录,记录结果为:
select * from t_7,t_8;
3、子查询数据源:数据来源是一个select对应的查询结果
select * from (select * from t_7,t_8) t; # 数据有冲突查不出来
select * from (select * from t_7) as t;
4、如果有时候名字较长或者使用不方便,可以利用表别名
select * from t_1 as t;
select t1.*,t2.stu_name from t_1 as t1,t_2 t2;
where子句:跟在from数据源之后,对数据进行条件匹配,筛选数据的
示例
1、查询t_5表中学生为lily的成绩信息
select * from t_5 where stu_name = 'Lily';
2、因为where是在磁盘取数据时进行条件筛选,此时数据没有进入内存,所以字段别名是无效的
# 错误
select stu_name name,score from t_5 where name = 'Lily';
运算符:用于进行运算的符号
>
(大于)、<
(小于)、=
(等于)、>=
(大于等于)、<=
(小于等于)、<>
(不等于)between A and B
:A和B之间(A小于B),包括A和B本身(数值比较)in (数据1,数据2,...数据N)
:在列举的数据之中like 'pattern'
:像上面样的,用于字符串比较
_
:单下划线,匹配对应位置的一个任意字符(ab_:ab开头+一个字符,匹配abc,ab1,但不能匹配abcd)%
:匹配当前位置(往后)任意数量任意字符(ab%:ab开头+任意数量任意字符,匹配abc,ab1,abcd)and
(逻辑与)、or
(逻辑或)、not
(逻辑非)is null
(为空)、is not null
(不为空)示例
1、查询成绩不及格的所有学生信息
# 成绩条件:成绩是数值,又是比大小,可以直接使用比较运算符
select * from t_5 where score < 60;
2、查询成绩在60-90间的学生信息
# 成绩条件:区间60到90,可以有两种解决方案
select * from t_5 where score between 60 and 90;
select * from t_5 where score >= 60 and score <= 90;
3、查询还没有成绩的学生
# 成绩条件:成绩为null,所以不能用比较符号查,只能使用is null实现
select * from t_5 where score is null;
group by子句:分组统计,根据某个字段将所有的结果分类,并进行数据统计分析
聚合函数:
group_concat()
:将组里的某个字段全部保留any_value()
:不属于分组字段的任意一个组里的值count()
:求对应分组的记录数量
count(字段名)
:统计某个字段值的数量(NULL不统计)count(*)
:统计整个记录的数量(较多)sum()
:求对应分组中某个字段是和max()/min()
:求对应分组中某个字段的最大/最小值avg()
:求对应分组中某个字段的平均值示例
1、创建一张表,存储学生信息
create table t_0(
id int primary key auto_increment,
name varchar(10) not null,gender enum('男','女','保密'),
age tinyint unsigned not null,
class_name varchar(10) not null comment '班级名称'
)charset utf8;
insert into t_0 values
(null,'鸣人','男',18,'木叶1班'),(null,'佐助','男',18,'木叶1班'),(null,'佐井','男',19,'木叶2班'),
(null,'大蛇丸','男',28,'木叶0班'),(null,'卡卡西','男',29,'木叶0班'),(null,'小樱','女',18,'木叶1班'),
(null,'雏田','女',18,'木叶1班'),(null,'我爱罗','男',19,'木叶1班'),(null,'向日葵','女',6,'木叶10班'),
(null,'博人','男',8,'木叶10班'),(null,'鼬','男',28,'木叶0班');
2、统计每个班的人数
select count(*),class_name from t_0 group by class_name;
3、多分组:统计每个班的男女学生数量
select count(*),class_name,gender from t_0 group by class_name,gender;
4、统计每个班里的人数,并记录班级学生的名字
select count(*),group_concat(name),class_name from t_0 group by class_name;
select count(*),any_value(name),class_name from t_0 group by class_name;
分组原理:
以统计班级学生为例
回溯统计:在进行分组时(通常是多分组),每一次结果的回溯都进行一次汇总统计
with rollup
示例
统计每个班的男女同学数量,同时要知道班级人数总数
# 只统计每个班的男女同学数量,没有班级汇总
select count(*),class_name,gender,group_concat(name) from t_40 group by class_name,gender;
# 汇总统计:回溯
select count(*),class_name,gender,group_concat(name) from t_40 group by class_name,gender with rollup;
回溯统计原理:
分组排序:在分组后统计结果时可以根据分组字段进行升序或者降序显示数据
group by 字段名 [ASC]
:升序排序(默认)group by 字段名 DESC
:降序排序示例
1、对分组结果女性优先显示:gender为枚举,男值为1,女值为2
select count(*),class_name,gender,group_concat(name),any_value(name)
from t_0 group by class_name,gender desc;
having子句:类似于where子句,是用来进行条件筛选数据的
示例
1、获取班级人数小于3的班级
select count(*) as count,class_name,group_concat(name) from t_0 group by class_name having count < 3;
# 多用了一次函数(效率降低)
select count(*) as count,class_name,group_concat(name) from t_0 group by class_name having count(*) < 3;
# 没办法,前面没统计,只能自己统计
select class_name,group_concat(name) from t_0 group by class_name having count(*) < 3;
order by子句:排序,根据某个指定的字段进行升序或者降序排序
order by 字段 [ASC]
:升序order by 字段 DESC
:降序示例
1、单字段排序:给所有学生按照年纪大小升序排序
select * from t_0 order by age;
select * from t_0 order by age asc;
2、多字段排序:先性别降序排序,然后按年龄升序排序
select * from t_40 order by gender desc,age;
select * from t_40 order by gender desc,age asc;
limit子句:限制数据的获取数量(记录数)
limit 子句必须在order by子句之后(如果同时存在)
limit限制数量的方式有两种:
limit 数量
:限制获取的数量(不保证一定能获取到指定数量)limit 起始位置,数量
:限制数据获取的位置以及数量(分页)limit限制数量可以有效的减少服务器的压力和传输压力
常利用limit来实现分页获取数据
示例
1、获取t_0表中前3条数据
select * from t_0 limit 3;
2、获取t_0表中第3条以后的3条数据
select * from t_0 limit 3,3;select * from t_0 limit 6,3;
数据查询总结:
查询操作是所有操作里使用的最多也是最终的操作
查询操作的完整语法:select select选项 字段列表[别名] /* from 数据源[别名] where子句 group by子句 having子句 order by子句 limit 子句;
很多结构的组合其实可以达到同一效果,但是可能过程和效率会不同
限制更新:即更新时对更新的记录数进行限制
示例
1、对会员选3个发送10元红包(添加到账户)
create table t_1(
id int primary key auto_increment,
username varchar(50) not null unique,
password char(32) not null,
account decimal(10,2) default 0.00
)charset utf8;
insert into t_1 values(null,'username1','password',default),
(null,'username2','password',default),
(null,'username3','password',default),
(null,'username4','password',default),
(null,'username5','password',default);
update t_1 set account = account + 10 limit 3;
限制删除:限制要删除的记录数
示例
1、删除没有账户余额的一个用户(当前用户量少,一般数量会大些)
delete from t_1 where account = 0 limit 1;
清空数据:将表中的所有数据清除,并且将表的所有状态回到原始状态
truncate 表名
示例
1、清空用户数据表
truncate t_1;