查询
简单查询
- 查询单个字段
select 字段名 from 表名;
- 查询多个字段
select 字段名1,字段名2,... from 表名;
- 查询所有字段
select * from 表名;
注:企业开发中不建议使用 * 进行所有字段的查询。1、效率低 2、可读性差
更改查询结果的列名
select 原列名 as 新列名 from 表名;(as可以省略)
注:只改变查询结果的列名,对原数据库没有任何更改
列参与数学运算
字段可以使用数学表达式
select A*10 from B;
将A字段查询出来的所有数据都乘以10
条件查询
select ... from ... where 条件;
条件:
等于 | 不等于 | 小于,小于等于 | 大于,大于等于 | 两个值之间 | 空,非空 | 并且 | 或者 | 包含,不包含 |
---|---|---|---|---|---|---|---|---|
= | !=或<> | <,<= | >,>= | between ... and... | is null,is not null | and | or | in |
注:
- 使用between and,必须遵守左小右大。
- between and是闭区间,包含两端的值。
模糊查询
支持%或下划线匹配
%匹配任意字符
下划线,一个下划线只匹配一个字符
select A from B where name like '%C%';
(从B表查询字段A中带有C的数据)
select A from B where name like 'C%';
(从B表查询字段A中C开头的数据)
select A from B where name like '_C';
(从B表查询字段A中第二位为C的数据)
排序
- 升序
select A from B order by C asc;
(默认升序,asc可省略) - 降序
select A from B order by C desc;
- 多次排序
select A from B order by C desc,D asc;
(优先执行C的desc,只有当C中有相等数据时,将相等数据对应的D数据进行asc)
注:排序的执行顺序是在查询完之后对查询出的数据进行排序
函数
单行处理函数
特点:一个输入对应一个输出
常用的单行处理函数:
- Lower 转换成小写
select lower(name) from A;
- upper 转换成大写
select upper(name) from A;
- substr 截取子串
select substr(被截取的字符串,起始下标,截取的长度) from A;
注:起始下标从1开始 - length 取长度
select length(name) from A;
- trim 去空格
select sname from A where uname = trim(' zhangsan ');
- round 四舍五入
select round(1234.56,0) from A;
//保留到个位
select round(1234.56,1) from A;
//保留一位小数
select round(1234.56,-1) from A;
//保留到十位 - rand() 生成随机数
select rand() from A;
select round(rand()*100,0) from A;
//随机生成100以内的随机数 - Ifnull 将null转换成一个具体数
select Ifnull(字段,0) from A;
//该字段中所有null都当作数值0 - concat 拼接字符串
select concat(A,B) as C from A;
//将AB字段的每行数据对应拼接并用C字段显示 - case..when..then..when..then..else..end
select A (case A when a then b when c then d else e end) from B;
//A当中的数据为a则执行b,为c则执行d,都不为执行e,可以看作是if语句
分组函数
特点:输入多行,输出一行
count
获取记录数sum
求和avg
平均数max
最大min
最小
注:count(具体字段)会忽略null值。
所有分组函数能组合起来一起用。
分组函数一定不能直接用在where后。
分组
select ... from ... where ... group by ... order by;
//语句执行顺序 from -> where -> group by -> select -> order by
在select语句中,如果有group by语句,那么select后面只能跟参加分组的字段以及分组函数。
having
group by ... having ...;
可以对分完组后的数据进一步过滤,但必须跟group by联合使用。
执行顺序:group by -> having -> select
having不能代替where,一般优先使用where,实在不行再选择having。
where没办法处理的例子:
找出每个部门平均薪资,要求显示平均薪资高于3000
select A avg(sal) from B group by A having avg(sal)>3000;
distinct //去除查询结果的重复记录
distinct只能出现在所有字段的最前方,但可以运用在分组函数中。
select distinct A,B from C;
select sum(distinct A)from B;
连接查询(使用sql99语法)
根据表连接的方式
内连接
- 等值连接
表和表的连接条件是等值关系
select ... from a inner join b on a和b的连接条件 where 筛选条件;
select s.sname,t.tname from studnet s inner join teacher t on s.classroom = t.classroom wwhere ...;
- 非等值连接
表和表的连接条件不是等值关系
select s.sname,t.tname from studnet s inner join teacher t on s.age between t.minage and t.maxage;
- 自链接
将一张表看成两张表
select a.pname as '员工名' ,b.pname as '领导名' from people a join people b on a.mid = b.pid;
外连接
- 左外连接(左连接)
select s.sname,t.tname from studnet s left outer join teacher t on s.classroom = t.classroom;
//将join关键字左边的表看成主表,主要目的是将主表中的数据全部查出来,并捎带关联查询次表。
- 右外连接(右链接)
select s.sname,t.tname from studnet s right outer join teacher t on s.classroom = t.classroom;
//将join关键字右边的表看成主表,主要目的是将主表中的数据全部查出来,并捎带关联查询次表。
全连接
select s.sname,t.tname from studnet s full outer join teacher t on s.classroom = t.classroom;
//把两个表都看成主表全部查出来。
多表查询
select
...
from
a
join
b
on
a和b的连接条件
join
c
on
a和c的连接条件
子查询
select语句中嵌套select语句,被嵌套的select语句被称为子查询。
子查询可以出现的地方
select
..(select).
from
..(select). //from后的子查询可以将查询结果当作一张临时表。
where
..(select). //优先执行子查询,再执行总查询
union合并查询结果集
select语句1
union
select语句2;
数据量大的情况下,union效率要高于直接连接查询的效率
a 表 x 条数据
b 表 y 条数据
直接连接查询的次数:x*y
union查询次数:x+y
注:
- union在进行结果集合并的时候,要求两个结果集的列数相同。
- mysql语法中列的数据类型可以不同,oracle语法不行。
limit
作用:将查询结果集的一部分显示出来,通常用于分页查询中
limit startIndex, length;
(startIndex:起始下标,起始下标从0开始 length:长度)
select ... from ... order by ... limit;
mysql中limit在order by后执行。
每页显示pageSize条记录
第pageNo页:limit(pageNo - 1)* pageSize ,pageSize;
insert
insert into 表名 (字段名1,字段名2,字段名3...) values (值1,值2,值3);
一次插入多条记录
insert into 表名 (字段名1,字段名2,字段名3...) values (),(),()...;
日期
str_to_data('字符串日期','日期格式')
%Y | %m | %d | %h | %i | %s |
---|---|---|---|---|---|
年(Y要大写) | 月 | 日 | 时 | 分 | 秒 |
str_to_data('18-05-2023','%d-%m-%Y')
如果提供的日期字符串是%Y-%m-%d的格式,则可以省略str_to_data()不写
('2023-05-18')
date_format(日期类型数据,'日期格式')
date_format(time,'%Y/%m/%d')
查询结果:2023/5/18
date和datetimem
date:短日期,只包括年月日
默认格式%Y-%m-%d
datetime:长日期,包括年月日时分秒
默认格式%Y-%m-%d %h:%i:%s
now()
在MySQL中获取系统当前时间,并且获取的时间是datetime类型。
update
update 表名 set 字段名1 = 值1, 字段名2 = 值1, 字段名3 = 值3 ... where 条件;
delete
delete from 表名 where 条件;
truncate
truncate table 表名
delete和truncate区别
delete:DML,表中数据删除,但数据在硬盘上的真实存储空间不会被释放,删除效率低,但可以回滚。
truncate:DDL,物理删除,删除效率高,但不支持回滚。
约束(constraint)
not null | unique | primary key | foreign key | check |
---|---|---|---|---|
非空约束 | 唯一性约束 | 主键约束 | 外键约束 | 检查约束(mysql不支持,oricle支持) |
存储引擎
MySQL默认存储引擎:InnoDB
MySQL默认字符编码:utf8
常用存储引擎
-
MyISAM存储引擎
使用三个文件表示每个表:- 格式文件:存储表结构的定义(mytable.frm)
- 数据文件:存储表行的内容(mytable.MYD)
- 索引文件:存储表上索引(mytable.MYI)
优势:
- 可被转换为压缩、只读表来节省空间。
-
InnoDB存储引擎
mysql默认的存储引擎,支持事务,支持数据库崩溃后自动恢复机制。- InnoDB表空间tablespace被用于存储表的内容
优势:
- 非常安全。
- 支持事务。
劣势:
- 效率慢
-
MEMORY存储引擎
使用MEMORY存储引擎的表,数据存储在内存中,且行的长度固定。优势:查询效率最高,不用于硬盘交互。
劣势:不安全,关机后数据消失。
事务
只有DML语句与事务有关。
数据操纵语言(DML)全称是Data Manipulation Language。
主要是进行插入元组、删除元组、修改元组的操作。主要有insert、update、delete语法组成。
本质上,,事务就是批量的DML语句同时成功或者同时失败
InnoDB存储引擎:提供一组用来记录事务性活动的目录。
在事务执行过程中,每一条DML操作都会记录到事务性活动的日志文件中。
在事务执行过程中,可以提交事务和回滚事务。
提交事务
- 清空事务性活动的日志文件,将数据全部持久化到数据库中。
- 提交事务表示着,事务的结束,并且是一种成功的结束。
commit;
回滚事务
- 将之前所有的DML操作撤销,并且清空事务性活动的日志文件。
- 回滚事务表示着,事务的结束,并且是一种错误的结束。
-rollback;
(回滚只能回滚到上一次的提交点)
transaction
mysql中默认是自动提交事务,即每执行一次DML语句,提交一次
start transaction;
(关闭自动提交事务)
事务的特性
- A(原子性):事务中包含的操作看成一个操作单元,这个操作单元要么成功,要么失败。
- C(一致性):事务完成时,数据必须处于一致状态,数据的完整性约束没有被破坏,在执行中如果发生错误,则回滚到事务开始前的状态。
- I(隔离性):事务允许多个用户对同一个数据进行并发访问,而不破坏数据的正确性和完整性,同时,事务的修改必须与其他并行事务的修改相互独立。
- D(持久性):事务结束后,事务处理的结果能保存到硬盘上。
隔离性四个级别
1.读未提交(最低的隔离级别)
- 事务A可以读到事务B未提交的数据。
- 存在脏读问题。
2.读已提交(oracle数据库默认的隔离级别)
- 事务A只能读取到事务B已提交的数据。
- 解决了脏读问题,但是不可重复读取数据。
3.可重复读(mysql数据库默认的隔离级别)
- 事务A开启后,每一次读取的都是一样的数据,即使事务B修改并提交了数据,事务A读取的数据还是一样的。
- 每次读取的数据不够真实,会产生幻读
注:不可重复读与幻读的区别
二者产生的原因都是因为读的过程中前后数据不一致,但不可重复读偏重于数据修改后数据内容不同,而幻读偏重于数据增删后数据数量不同。
所以在处理不可重复读与幻读的时候,前者只需要采用行级锁,而后者要使用表锁
4.序列化/串行化(最高的隔离级别)
- 事务排队,不能并发。
- 每次读取的数据最真实,但效率最低。
索引
索引是在数据库表的字段上添加的一种为了提高查询效率的机制。
t_student
id(idIndex) name(nameIndex) age(ageIndex) gender(genderIndex)
——————————————————————————————————
01 张三 19 男
02 李四 20 男
03 王五 21 男
select * from t_student where name = zhangsan"
如果name字段没有添加索引,mysql会将name字段上的每一个值都对比一边,效率很低。
任何数据库当中主键都会自动添加索引对象,在mysql中,字段上有unique约束,也会自动创建索引对象。
创建索引
create index A_B_index on A(B);
(给A表的B字段添加索引,起名为A_b_index)
删除索引
drop index A_B_index on A;
(将A表上的A_B_index索引对象删除)
索引失效
- like查询以%开头
- 查询条件中带有or,除非所有的查询条件都有索引,否则索引失效
- 如果列类型是字符串,那么在查询条件中要将数据用引号引用起来,否则索引失效
- 索引列上参与计算会导致索引失效
- 使用复合索引的时候,没有使用左侧的列查找
数据库设计三范式
第一范式
必须要有主键,并且每一个字段都具有原子性
第二范式
建立在第一范式的基础上,所有非主键字段都要完全依赖主键,不能产生部份依赖
第三范式
建立在第二范式基础上,所有非主键字段必须直接依赖主键,不要产生传递依赖
表的设计
一对多:两张表,多的表加外键
多对多:三张表,关系表两个外键
一对一:表中字段太多,将一张表拆成两张表