目录
一、分组与限制
1.分组过滤
语法:select 字段 from 表 where 条件 group by 字段 having 条件
分组过滤having和where类似,都是用于条件判断;
区别在于:where是最核心的条件判断; 但having只能用在分组的条件判断
#分组过滤:
#统计60、70、90号部门的最高工资
#思路:
#1). 确定分组依据(department_id)
select department_id from t_employees group by department_id;
#2). 对分组后的数据,过滤出部门编号是60、70、90信息
select department_id from t_employees group by department_id having department_id in(60,70,90);
#3). max()函数处理
select department_id,max(salary) from t_employees group by department_id having department_id in(60,70,90);
2.结果限制
#限定查询 限定查询出来的条数 SELECT 列名 FROM 表名 [LIMIT 起始行,查询行数]()
#应用场景:分页查询
#查询表中前五名员工的所有信息
select * from t_employees limit 0,5;#查询表中从第四条开始,查询 10 行
select * from t_employees limit 3,10;#分页: 每页5条 第1页:0,5 第2页:5,5 第3页:10,5
#算法: 起始行=(当前页-1)*每页条数
3.编写数据
select 字段 from 表 where 条件 group by 字段 having 条件 order by 字段 limit 起始行,条数
二、子查询
概述:会出现两个查询语句;一个查询的结果,是另一个查询的条件;这个结果就是子查询
1.单行单列
子查询的结果为单行单例;是最基本,也是最常用的一种子查询
#子查询--单行单列
#查询工资大于Bruce 的员工信息
#1.先查询到 Bruce 的工资(一行一列)
select salary from t_employees where FIRST_NAME='Bruce'; #子查询
#2.查询工资大于 Bruce 的员工信息
select * from t_employees where salary>6000;
#3.组合
select * from t_employees where salary>(select salary from t_employees where FIRST_NAME='Bruce');
2.多行单列
子查询的结果是多行单列的应用,往往有两种情况:1.枚举查询 2. all| any关键字
#枚举的多行单列: where 字段 in(值1,值2..)
#查询与名为'King'同一部门的员工信息
#思路:
#1. 先查询 'King' 所在的部门编号(多行单列)
select department_id from t_employees where LAST_NAME='King';
#2. 再查询80、90号部门的员工信息
select * from t_employees where department_id in(80,90);
#3.组合
select * from t_employees where department_id in(select department_id from t_employees where LAST_NAME='King');
#any|all的使用 any-匹配部分 all-匹配所有
#工资高于60部门所有人的信息
#1.查询 60 部门所有人的工资(多行单列)
select salary from t_employees where DEPARTMENT_ID=60;
#2.查询高于 60 部门所有人的工资的员工信息(高于所有-高于最高的)
select * from t_employees where salary > ALL(select salary from t_employees where DEPARTMENT_ID=60);
#。查询高于 60 部门的工资的员工信息(高于部分-高于最低的)
select * from t_employees where salary > ANY(select salary from t_employees where DEPARTMENT_ID=60);
3.多行多列
子查询的结果是一张虚拟表,继续当成表来使用即可
SELECT 列名 FROM(子查询的结果集)WHERE 条件;
#多行多列的子查询
#查询员工表中工资排名前 5 名的员工信息
#思路:
#1. 先对所有员工的薪资进行排序(排序后的临时表)
select * from t_employees order by salary desc;
#2. 再查询临时表中前5行员工信息
select * from (select * from t_employees order by salary desc) temp limit 0,5;
#简化写法:
select * from t_employees order by salary desc limit 0,5;
三、关联查询
1.合并查询
合并查询,需要合并多张表;在平时应用中不常用;合并的表字段数量要一致,否则会有问题
应用场景:多张表结构一致,并进行汇总才用到; 例如:多个班级学生信息汇总
#创建t1表和t2表
#合并查询
#合并两张表的结果,去除重复记录
select * from t1 UNION select * from t2;
#合并两张表的结果,不去除重复记录(显示所有)
select * from t1 UNION ALL select * from t2;
2.表连接查询
表连接查询分为:内连接和外连接
内连接:两张表中能够匹配上的记录则显示出来;匹配不上的,则不显示
外连接分为左外和右外:
左外:以左表为标准,所有记录都会显示;如果右表记录匹配不上则显示为null
右外:以右表为标准,所有记录都会显示;如果左表记录匹配不上则显示为null
#创建teacher表和couse表
#内连接:
select * from teacher t,couse c where t.id=c.t_id; #MySQL专用
select * from teacher t INNER JOIN couse c ON t.id=c.t_id; #统一标准
#左外连接
select * from teacher t LEFT JOIN couse c ON t.id=c.t_id;
#右外连接
select * from teacher t right JOIN couse c ON t.id=c.t_id;
#三表关联案例:
#查询所有员工工号、名字、部门名称、部门所在国家ID
#员工工号、名字-员工表; 部门名称-部门表 国家ID-地区表
select e.employee_id,e.first_name,d.DEPARTMENT_NAME,l.COUNTRY_ID from t_employees e
INNER JOIN t_departments d ON e.DEPARTMENT_ID=d.DEPARTMENT_ID
INNER JOIN t_locations l ON d.LOCATION_ID=l.LOCATION_ID;
四、DML操作
DML是数据操作语言,针对表中的增删改的操作; 查询则叫做DQL
1.添加
语法1:insert into 表名(字段1,字段2..) values(值1,值2...) ---常用
语法2:insert into 表名 values(值1,值2...) 必须和表字段一一对应,且全部字段要添加数据(如果id为主键自增可以设置null填入)
#添加一条工作岗位信息
insert into t_jobs(job_id,job_title,min_salary,max_salary) values('AD_IT','IT_PRO',10000,20000); #推荐
insert into t_jobs values('AD_XS','XSY',5000,15000); #注意:字段必须按顺序,且写全
2.删除
语法: delete from 表 where 条件
注意:必须要加where,否则删除表的所有记录
#删除编号为135 的员工
delete from t_employees where employee_id=135;
#删除姓Peter,并且名为 Hall 的员工
delete from t_employees where first_name='Peter' and last_name='Hall';
#清除数据表
TRUNCATE table teacher; #类似delete from teacher 区别:TRUNCATE 删除表再重新创建
五、数据表操作
1.数据类型
建表前,需要先弄清除数据库的数据类型分类,可以分为:数值类型,日期类型,字符串类型
这些类型重点记住:int,double(M,D), date,datetime,varchar(长度)
2.创建表
建表前,需要先弄清除数据库的数据类型分类,可以分为:数值类型,日期类型,字符串类型
这些类型重点记住:int,double(M,D), date,datetime,varchar(长度)
3.数据表操作
#表字段的操作: ALTER TABLE 表名 操作;
#在课程表基础上添加gradeId 列
alter table sub add gradeId int;
#修改课程表中课程名称长度为10个字符
alter table sub MODIFY name varchar(10);
#删除课程表中 gradeId 列
alter table sub drop gradeId;
#修改课程表中 hour 列为 h
alter table sub change hour h int;
#修改课程表的sub 为 subs
alter table sub rename subs;
#删除subs表
drop table subs;
六、约束
问题:在往已创建表中新增数据时,可不可以新增两行相同列值得数据?]()
如果可行,会有什么弊端?
答:可以创建;弊端:无法识别唯一的一条记录; 造成数据的读写肯定会出问题; 需要进行约束
1.实体完整性约束
一条记录代表着一个实体对象,也是就每条记录都需要唯一性约束
主键约束
表中每条记录的唯一标识,不代表业务逻辑; 注意:主键不能为null
唯一约束
主键约束就是唯一约束,区别在于唯一约束设置到除id以外的字段;且允许为null
主键自增长
主键自增长,默认从1开始,每次添加都+1;添加数据更方便
#主键约束:
create table sub(
id int primary key auto_increment, #主键约束,不能为null 自增长
name varchar(20) UNIQUE, #唯一约束
hour int
)
select * from sub;
insert into sub(name,hour) values('java',60);
insert into sub(name,hour) values('h5',55);
2.域完整性约束
域完整性约束是针对字段中的单元格的值的范围的限制
create table sub(
id int primary key auto_increment,
name varchar(20) UNIQUE not null, #非空约束
hour int default 30 #默认值为30
)
select * from sub;
insert into sub(name) values('java');
insert into sub(name,hour) values('h5',55);
3.外键约束
两张表中的单元格的值的范围限制; 这两张表一张作为主表,一张作为从表
主表:关联字段的主键所在表为主表;关联字段的非主键所在表则是从表
外键约束规则:(注意:外键约束需要设置到从表中)
创建时,先创建主表;添加数据时,先添加主表数据
删除时,先删除从表或数据;再删除主表或数据
#外键约束
drop table teacher; #主表
drop table course; #从表
#先创建主表 创建时先创建主表及添加数据
create table teacher(
id int primary key auto_increment,
name varchar(20)
);
insert into teacher(name) values('凤姐');
insert into teacher(name) values('芙蓉');
select * from teacher;
#再创建从表,并设置外键约束
create table course(
id int primary key auto_increment,
name varchar(30),
t_id int, #外键 从表中的关联字段是外键
#CONSTRAINT 标记名 FOREIGN KEY(外键名) REFERENCES 主表(主键)
CONSTRAINT fk FOREIGN KEY(t_id) REFERENCES teacher(id) #外键约束
);
select * from course;
insert into course(name,t_id) values('h5',1); #添加时t_id只能时主键中存在的1或2的主键值
#删除时,先删从表或数据,再删主表或数据
七、事务
1.概述
事务是原子性操作(不可分割的整体);处在事务中的多个SQL语句,要么都成功,则提交;要么都失败,则回滚
2.事务的边界
事务的边界,就是事务开启或结束的过程
开始: 启动事务 start transaction; 开启事务后,则进入事务中;中间可执行SQL语句
执行多条SQL语句
结束:(提交或回滚)
提交:多条SQL语句都执行成功,则提交; commit;
回滚:如果有任意SQL语句失败,则回滚,回滚到未发生的状态; rollback;
3.原理
开启事务后,相当于开辟了缓冲区(回滚段);所有SQL指令的执行都是在缓冲区中进行;如果都成功了,则执行提交,意味着提交到数据库中永久写入;如果有失败的,则执行回滚(清除缓冲区)
4.事务特性
事务特性:ACID; 原子性,一致性,隔离性,持久性
原子性:事务操作要么都成功,要么都失败
一致性:事务的成功或失败,最终完成的状态是一致的(例如,转账的总和不变)
隔离性:处在事务中,与外界的操作是完全隔离的;除非进行了提交或回滚
持久性:进行了提交,则永久性写到了数据库中
1.应用
#事务的操作 ---模拟转账功能
#zs和ls都有1000块;zs转200给ls
create table account(
id int primary key auto_increment,
name varchar(20),
money int
)
insert into account(name,money) values('zs',1000);
insert into account(name,money) values('ls',1000);
select * from account;
start TRANSACTION; #开启事务
update account set money=money-200 where name='zs';
#中途出现异常,则会跳到回滚语句
update account set money=money+200 where name='ls';
commit; #上述的SQL操作无异常,则进入提交
rollback; #如果有一条语句出现异常,则会跳到回滚
八、权限管理
创建一个用户,并指定好操作权限(增删改查权限)
#权限管理
#创建用户
create user 'zs' IDENTIFIED by '123';
#给用户分配权限
GRANT ALL ON mydb1.* to 'zs';
#撤销用户权限
REVOKE ALL ON mydb1.* from 'zs';
#删除用户 zs
drop user 'zs';
九、视图
1.概述
视图就是一张虚拟表;从原表中抽取出来的虚拟表; 关于虚拟表的操作,也会联动的改变原表
好处:
1.屏蔽了原表的重要数据,提升安全性
2.当需要从多表中提取数据时,使用视图可以提升性能
缺点:
1.单表的操作,会变得复杂(增删改的操作要联动原表)
2.复杂的视图是无法被修改的 例如:聚合函数形成的视图
2.应用
#视图操作:
#创建视图 创建 t_emp 的视图,其视图从 t_employees 表中查询到员工编号、员工姓名、员工邮箱、工资
create view t_emp as select employee_id,first_name,email,salary from t_employees;
#视图的操作,与原表一致的;且会联动改变原表
select * from t_emp;
select * from t_employees;
update t_emp set salary=30000 where employee_id=100;
#修改视图
#方式1:创建或替换视图 存在则替换,不存在则创建
create or REPLACE view t_emp as select employee_id,salary from t_employees;
#方式 2:直接对已存在的视图进行修改
alter view t_emp as select employee_id,first_name,email,salary from t_employees;
#删除t_emp视图
drop view t_emp;
#视图的注意事项:如果视图是聚合函数或分组形成的,则不能变更
create view emp as select count(*) as count from t_employees;
select * from emp;
update emp set count=5;
十、SQL分类与综合练习
1.SQL语言分类
数据查询语言DQL(Data Query Language):select、where、order by、group by、having 。
数据定义语言DDL(Data Definition Language):create、alter、drop。
数据操作语言DML(Data Manipulation Language):insert、update、delete 。
事务处理语言TPL(Transaction Process Language):commit、rollback 。
数据控制语言DCL(Data Control Language):grant、revoke。
2.综合案例
#查询所有用户的订单
select * from user u INNER JOIN orders o ON u.userId=o.userId;
#查询用户id为 1 的所有订单详情
select * from user u INNER JOIN orders o ON u.userId=o.userId
inner JOIN orderitem oi ON o.oid=oi.oid and u.userId=1;
#查看用户为张三的订单
#先查用户张三的userid
select userId from user where username='张三';
#再匹配userID为1的订单
select * from orders where userId = (select userId from user where username='张三');
#查询出订单的价格大于800的所有用户信息。
#先查询订单大于800的userId
select DISTINCT userId from orders where totalprice>800;
#再使用枚举查询
select * from user where userId in (select DISTINCT userId from orders where totalprice>800);