DB:DataBase(数据库,数据库实际上在硬盘上以文件的形式存在)
DBMS:DataBase Management System(数据库管理系统,常见的有:MySQL,Oracle,DB2,Sybase,SqlServer...)
SQL:结构化查询语言,是一门标准通用的语言。
DBMS负责执行SQL语句,通过执行SQL语句来操作DB中的数据
表:table是数据库基本的组成单元,所有的数据都以表格的形式,目的是可读性强
? 一个表包括行和列,行被称为数据(data)或者是记录,列被称为字段(column)
? 字段名、数据类型,相关的约束
一个完成的SELECT语句包含可选的几个子句。SELECT语句的定义如下:
SQL代码
<SELECT clause> [<FROM clause>] [<WHERE clause>] [<GROUP BY clause>] [<HAVING clause>] [<ORDER BY clause>] [<LIMIT clause>]
SELECT语句中子句的执行顺序与SELECT语句中子句的输入顺序是不一样的,所以并不是从SELECT子句开始执行的,而是按照下面的顺序执行:
开始->FROM子句->WHERE子句->GROUP BY子句->HAVING子句->ORDER BY子句->SELECT子句->LIMIT子句->最终结果
比较运算符 | 说明 |
---|---|
= | 等于 |
< | 小于 |
<= | 小于等于 |
> | 大于 |
>= | 大于等于 |
<=> | 安全的等于,不会返回 UNKNOWN |
<> 或!= | 不等于 |
IS NULL 或 ISNULL | 判断一个值是否为 NULL |
IS NOT NULL | 判断一个值是否不为 NULL |
LEAST | 当有两个或多个参数时,返回最小值 |
GREATEST | 当有两个或多个参数时,返回最大值 |
BETWEEN AND | 判断一个值是否落在两个值之间 |
IN | 判断一个值是IN列表中的任意一个值 |
NOT IN | 判断一个值不是IN列表中的任意一个值 |
LIKE | 通配符匹配,模糊查询,_代表任意一个字符,%代表任意多个字符 |
REGEXP | 正则表达式匹配 |
avg
平均值,sum
求和,max
最大值,min
最小值,count
计数where
后面。group by
联合使用,在group by
执行完之后再执行ifnull(可能出现null的字段,把这个null当作什么来处理)
group by
和 having
group by
:按照某个字段或者某些字段进行分组
having
:对分组之后的数据进行再次过滤
group by
可以多个字段分组,只要在字段后面加,
就好了。优先前面的
#案例:找出每个部门不同工作岗位的最高薪资
select deptno,job,max(sal) from emp group by deptno,job
当一条语句后面有group by
时,select
后面只能跟参加分组的字段和分组函数
distinct
? distinct
只能出现在所有字段的最前方,如果后面有多个字段,就是多个字段联合去重(多个字段不重复的,第一个字段重复,但是第二字段不重复就不算重复)
案例:统计岗位的数量
select count(distinct job) from emp;
根据表的连接方式来划分,分为:
最大的特点:条件是等量关系
案例:查询每个员工的部门名称,要求显示员工名和部门名
SQL92语法
select e.ename,d.dname from emp e,dept d where e.deptno = d.deptno
SQL99语法
select e.ename,d.dname from emp e join dept d on e.deptno = d.deptno
99语法更清晰,因为表连接的条件和where条件分离了
最大的特点:条件是非等量关系
案例:找出每个员工的工资等级,要求显示员工名、工资、工资等级
select e.ename,e.sal,s.grade from emp e inner join salgrade s on e.sal between s.losal and s.hisal;
inner
表示内连接,可以省略不写
最大的特点是:一张表看作两张表,自己连接自己
案例:找出每个员工的上级领导,要求显示员工名和对应的领导名
select a.ename as ‘员工名‘,b.ename as ‘领导名‘ from emp a inner join emp b on a.mgr = b.empno;
什么是外连接?和内连接的区别?
内连接:
? 假设A和B表进行连接,使用内连接的话,凡是A表和B表能够匹配上的记录查询出来,这就是内连接。AB表没有主副之分
外连接:
假设A和B表进行连接,使用外连接的话,AB两张表有主副之分,主要查询主表的数据,捎带查询副表,当副表中的数据没有和主表的数据匹配上,副表自动模拟出NULL与之匹配
左外连接:表示左边的这张表是主表
右外连接:表示右边的这张表是主表
左外连接有右外连接的写法,右连接也会有对应的左连接的写法
select a.ename ‘员工‘,b.ename ‘领导‘ from emp a left join emp b on a.mgr = b.empno
select d.* from emp e right join dept d on e.deptno = d.deptno where e.empno is null;
select e.ename,d.dname,s.grade from emp e join dept d on e.deptno = d.deptno join e.sal between s.losal and s.hisal;
增加难度:找出每个员工的部门名称、工资等级以及上级领导(如果没有上级领导也要展示数据)
select e.ename ‘员工名称‘,d.dname,s.grade,e1.ename ‘领导名称‘ from emp e join dept d on e.deptno = d.deptno join e.sal between s.losal and s.hisal left join emp e1 on e.mgr = e1.empno;
select语句当中嵌套select语句,被嵌套的select语句是子查询。
子查询可以出现在select 后面,from后面,where后面
where语句中使用子查询就是相当于把查询结果当成一个条件
案例:找出高于平均薪资的员工信息
select * from emp where sal > (select avg(sal) from emp);
from后面嵌套子查询就是相当于把查询出来的结果当成一个新表
案例:找出每个部门平均薪水的薪资等级
select t.*,s.grade from (select deptno,avg(sal) as avgsal from emp group by deptno) t join salgrade s on t.avgsal between s.losal and s.hisal
案例:找出每个员工所在的部门名称,要求显示员工名和部门名
不使用子查询的写法
select e.ename,d.dname from emp e join dept d on e.deptno = d.deptno;
使用子查询
select e.ename,(select d.dname from dept d where e.deptno = d.deptno) as dname from emp e;
可以将查询结果集相加
案例:找出工作岗位是SALESMAN和MANAGER的员工
第一种:select ename,job from emp where job = ‘MANAGER‘ or job = ‘SALESMAN‘
;
第二种:select ename,job from emp where job in(‘MANAGER‘,‘SALESMAN‘);
使用union:
select ename,job from emp where job = ‘MANAGER‘ union select ename,job from emp where job = ‘SALESMAN‘
如果是两张毫无相干的表,可以使用union连接,但是查询的列必须相同
limit是MySQL特有的,其他数据库没有,不通用。
limit取结果集的部分数据,这是它的作用。
语法机制:limit starIndex,length
,starIndex表示起始位置,length表示取几个
案例:找出工资前五名的员工
select ename.sal from emp order by desc limit 0,5;
直接写一个数字表示默认从第1个开始。下标从0开始。
每页显示3条记录:
第1页:0,3
第2页:3,3
第3页:6,3
规律:
每页显示pageSize
条记录:
第pageNum
页:(pageNum-1)*pageSize,pageSize
建表语句的语法格式:
create table 表名(
字段名1 数据类型 default 1, //default表示默认值,如果插入语句没有插入字段1,默认插入1
字段名2 数据类型,
字段名3 数据类型,
...
);
关于MySQL当中字段的数据类型(一下只说常见的)
类型 | 描述 |
---|---|
int(长度) | 整型 |
bigint(长度) | 长整型 |
char(长度) | 定长字符串,存储空间大小固定 |
float(有效数字位数,小数位) | 数值型 |
varchar(长度) | 变长字符串,存储空间等于实际数据空间 |
date | 日期型,年月日 |
datetime | 日期型,年月日 时分秒 毫秒 |
BLOB | Binary Large OBject (二进制大对象) |
CLOB | Character Large OBject(字符大对象) |
语法格式:
insert into 表名(字段名1,字段名2,字段名3,...) values(值1,值2,值3,...);
要求:字段的数量和值的数量相同,并且数据类型对应,表名后面可以不表明要插入的字段,默认全部插入,也可以写部分字段,其他字段为null
insert into t_student(no,name,sex,classno,birth)
values
(3,‘rose‘,‘1‘,‘高一三班‘,‘1997-11-09‘),
(4,‘jack‘,‘0‘,‘高一三班‘,‘1997-10-22‘);
可以一次插入多行,用逗号隔开
语法:
create table 表名 as select语句;
将查询结果作为表创建出来
insert into 表名 select语句;
将查询结果插入到一张表中
语法格式:
update 表名 set 字段名1=值1,字段名2=值2... where 条件;
注意:没有条件整张表数据全部更新
语法格式:
delete from 表名 where 条件;
注意:没有条件全部删除
怎么删除大表?
truncate table 表名;
用truncate删除后数据永久丢失,不可回滚
什么是约束?常见的约束有哪些?
在创建表的时候,可以给表的字段添加相应的约束,约束就是为了保证表中的数据的唯一性,合法性,有效性等等
常见的约束:
auto_increment
create table t_user(
id int primary key auto_increment,
username varchar(255)
);
为什么要用外键?用一个案例来解释
业务背景:请设计数据库表,来维护学生和班级的信息
第一种方案:一张表存储所有的信息
no(pk) | name | classno | classname |
---|---|---|---|
1 | 张三 | 101 | 高三一班 |
2 | 李四 | 101 | 高三一班 |
3 | 王五 | 102 | 高三二班 |
缺点:班级信息是固定只有那么几个,这么做会使数据【冗余】,不推荐
第二种方案:两张表(学生表和班级表),用外键来连接两个表的关系
t_class 班级表
cno(pk) | cname |
---|---|
101 | 高三一班 |
102 | 高三二班 |
t_student 学生表
sno(pk) | sname | cno(该字段添加外键约束fk) |
---|---|---|
1 | 张三 | 101 |
2 | 李四 | 101 |
3 | 王五 | 102 |
t_student
中的cno
字段引用t_class
表中的cno
字段,此时t_student
表叫做子表,t_class
表叫做父表。
删除数据时先删除子表,再删除父表,添加数据时,先添加父表,再添加子表
创建表时先创建父表,再创建子表,删除表时先删除子表,再删除父表
以上两张表的建表语句
create table t_class(
cno int,
cname varchar(255),
primary key(cno)
);
create table t_student(
sno int primary key,
sname varchar(255),
cno int,
foreign key(cno) references t_class(cno)
);
一个事务是一个完整的业务逻辑单元,不可再分。
比如:银行账户转账,从A账户向B账户转账1000,需要执行两条update语句。
update t_act set balance = balance - 1000 where actno = ‘act-001‘;
update t_act set balance = balance + 1000 where actno = ‘act-002‘;
以上两条DML语句必须同时成功,或者同时失败,不允许出现一条成功,一条失败。
要想保证以上的两条DML语句同时成功或者同时失败,就需要使用数据库的事务机制。
只有DML语句才和事务有关系(insert,delete,update)
原子性:事务是最小的工作单元,不可再分。
一致性:事务必须保证数据的一致性,要么全部成功,要么全部失败。
隔离性:事务A与事务B之间具有隔离。
持久性:数据必须持久化到硬盘文件中。
事物之间存在隔离级别,理论上隔离级别包括4个:
Oracle数据库默认的隔离级别是:读已提交
MySQL数据库默认的隔离级别是:可重复读
MySQL事务默认情况下是自动提交的。(什么是自动提交?只要执行任意一条DML语句则提交一次)
怎么关闭自动提交?start transaction
,这也是开启事务
start transaction
开启事务
commit
提交事务
rollback
回滚事务(回滚到上一次事务结束的点)
提交事务和回滚事务都会导致事务结束
? 索引就相当于一本书的目录,通过目录就可以快速的找到对应的资源,在数据库方面,查询一张表的时候,有两种查询方式。
第一种方式是全表扫描。
第二种方式是根据索引检索(效率很高)。
索引虽然可以提高检索效率,但是不能随意的添加索引,因为索引也是数据库中的对象,也需要数据库维护。是有维护成本的。比如,表中的数据经常被修改,这样就不适合添加索引,因为数据一旦修改,索引需要重新排序,进行维护。
添加索引是给某一个字段,或者是某些字段添加索引
创建索引
create index 索引名 on 表名(字段名);
删除索引
drop index 索引名 on 表名;
where
子句中unique
约束的字段会自动添加索引,根据主键查询效率较高,尽量根据主键检索。sql
语句的执行计划可以在sql
语句前面加 explain
关键字来查看该sql
的执行计划
索引底层采用的数据结构是:B+Tree
? 通过B Tree
缩小扫描范围,底层索引进行了排序,分区,索引会携带数据在表中的“物理地址”,最终通过索引检索到数据后,获取到关联的物理地址,通过物理地址定位表中的数据,效率是最高的。
unique
约束的字段会自动添加索引模糊查询时,第一个通配符使用的是%,这个时候索引是失效的,会全盘扫描
站在不同的角度去看待数据。(同一张表的数据通过不同的角度去看待)。
创建视图:
create view 视图名 as select语句;
只有DQL语句才能以视图对象的方式创建出来
删除视图:
drop view 视图名;
对视图进行增删改查会影响原表数据。通过视图影响原表数据的,不是直接操作的原表。
视图的增删改查和表的增删改查语句是一样的
视图可以隐藏表的实现细节。保密级别较高的系统,数据库只对外提供相关的视图,程序员只对视图对象进行CRUD。
第一范式:任何一张表都应该有主键,每一个字段原子性不可再分。
第二范式:所有非主键字段完全依赖主键,不能产生部份依赖。第二范式建立在第一范式的基础之上。
第三范式:所有非主键字段直接依赖主键字段,不能产生传递依赖。第三范式建立在第二范式的基础之上。
原文:https://www.cnblogs.com/lxs1204/p/14413463.html