DML语句(数据库操作语句)
如果涉及到对表的数据进行了变动(新增数据,修改数据,删除数据)
就需要进行保存(commit;)或者取消(rollback;)
保存/提交commit;
取消/回滚rollback;
插入数据
语法:
insert into 表名(列1,列2,列3) values(值1,值2,值3);
如果对整个表的所有列都需要增加数据
insert into 表名 values(值1,值2,值3);
- 日期格式
to_date()
to_date('2019-12-16','YYYY-MM-DD')
to_date('20081115','YYYYMMDD')
insert into stu values(7,'张二',to_date('20081115','YYYYMMDD'))
删除数据
delete from 表名 where 条件
- 删除stu表中 id 小于5的数据
delete from stu where id < 5;
- 如果有多个条件 记得使用 and 或者 or 来将条件进行连接
删除 id小于3 或者 id 大于8的数据
delete from stu where id < 3 or id >8;
修改数据
update 表名 set 列1=值1,列2=值2 where 条件
- 将stu表中,id为12的 学生的姓名修改为'王五'
update stu set name='王五' where id=12;
- 关于空值(null),在where中不能够使用 =null 或者 != null ,而是使用 is null 或者 is not null
-- 将stu表中,所有name为空的信息,将其id修改为22
update stu set id=22 where name is null;
查询语句
如无意外,接下来的教程,将以emp
表和dept
表为例子
表介绍
emp表(员工信息表)
字段 | 含义 |
---|---|
empno | 员工工号/编号 |
ename | 员工姓名 |
job | 员工工种/职位 |
mgr | 员工的上级的工号 |
hiredate | 入职日期 |
sal | 工资/薪水 |
comm | 奖金 |
deptno | 部门编号 |
- JOB职位讲解:
职位 | 含义 |
---|---|
CLERK | 秘书 |
SALESMAN | 销售 |
MANAGER | 经理 |
ANALYST | 分析员 |
PRESIDENT | 董事长 |
dept表(部门表)
字段 | 含义 |
---|---|
deptno | 部门编号 |
dname | 部门名称 |
loc | 部门地址 |
基本的查询语句
语法
select * from 表名; * 表示所有列
select 列名1,列名2 from 表名;
>查询出所有员工的姓名以及工资
select ename,sal from emp;
<br>
带条件的查询 where 条件
>查询出工资大于1500的所有的员工的姓名以及工种
select ename,job from emp where sal > 1500;
>查询出工资大于2000,并且部门号为20 员工的所有信息
select * from emp where sal>2000 and deptno=20;
>查找出奖金超过其工资的雇员的姓名、工资、奖金和工种的信息
select ename,sal,comm,job from emp where comm > sal;
> 每个月22个工作日算,查找出每个人的日薪
select ename,sal,sal/22 from emp;
去重 distinct
>查找出公司有多少种职位
select distinct job from emp;
模糊查询 like
%
表示任意长度的字符
> 查询出姓名以A开头的员工的信息
select * from emp where ename like 'A%';
> 查询出姓名以K结尾的员工的信息
select * from emp where ename like '%K';
> 查询出姓名中包含了A的员工的所有信息
select * from emp where ename like '%A%';
_
表示一个字符
> 查找出姓名以W开头,以D结尾,长度为4的 员工的信息
select * from emp where ename like 'W__D';
> 查找出姓名以A开头,长度为5的 员工的信息
select * from emp where ename like 'A____';
> 查找出emp表中经理号(MGR)为空的职工的有关信息
select * from emp where mgr is null;
between and 表示一个范围
- between 1000 and 2000 表示在1000~2000之间
- not between 1000 and 2000 表示在1000~2000之外
> 查找出工资在1000-2000之间的职工信息
select * from emp where sal between 1000 and 2000;
> 查找出工资在1000-2000之外的职工信息
select * from emp where sal not between 1000 and 2000;
in/not in 属于/不属于
> 查找出工资是1500或者是2000或者是3000的职工的所有信息
select * from emp where sal in (1500,2000,3000);
> 查找出工资不是1500、2000、3000的职工的所有信息
select * from emp where sal not in (1500,2000,3000);
> #### 随堂练习1
- 查找出全部经理 和 第10号部门秘书的有关信息
- 查找出不是30号部门中的所有经理的所有信息。
- 查找出工资在2000到3000之间的职工姓名、工种和工资
- 查找出工资在2500到3500之外的职工姓名、工种和工资
- 查询出全部秘书、分析员或推销员的姓名、工种、工资和所在部门号
- 查找出没有奖金的员工的姓名、工种、工资和部门号
order by 列名/字段
对查询的结果进行一个排序,默认升序
将emp表中的信息,根据工资升序排序
select * from emp order by sal;
升序的另外一种写法,在列名后面加上asc(默认是可以忽略的)
select * from emp order by sal asc;
如果想要降序排序,则在列名后面加上desc
将emp表中的信息,根据工资降序排序
select * from emp order by sal desc;
> #### 随堂练习
- 查找出每个销售人员的姓名以及年度总报酬,并按总报酬由高到低顺序显示
- 查找出工资高于1000元的职工的姓名、工种、工资和部门号,并按部门号由小到大排序显示
- 查找出奖金超过本人基本工资3%的职工的姓名,工资,奖金,奖金与工资的比例,并按其比例由高到低显示
order by 还可以根据多个列来进行排序
order by 列1,列2
表示先根据列1排序,如果列1相同的,再根据列2排序
查找工资大于1000的员工的姓名,工资,部门号并且按照部门号降序排序,同一个部门的按照工资的降序排序
select ename,sal,deptno from emp
where sal > 1000
order by deptno desc,sal desc;
练习:按工种升序,而同工种按工资降序排列显示全部职工的姓名,工种,工资。
分组函数/聚合函数/统计函数
分组函数 | 作用 |
---|---|
count(*) | 统计表中所有行的行数 |
count(字段) | 统计表中指定字段的非空行数 |
sum(字段) | 统计指定字段的和 |
avg(字段) | 统计指定字段的平均值 |
max(字段) | 统计指定字段的最大值 |
min(字段) | 统计指定字段的最小值 |
计算出公司的人数
select count(*) from emp;
计算出公司有多少个职位
select count(distinct job) from emp;
计算出所有员工的总工资,平均工资 、最大工资和最少工资
select sum(sal),avg(sal),max(sal),min(sal) from emp;
GROUP BY 列名
根据这个列来进行分组,列的值相同的分到同一个组中
比如group by deptno
就表示根据部门号分组,部门号相同的就分到同一个组中。
计算出每个部门的平均工资
思路:先根据部门号进行分组,部门号相同的分到同一个组中,然后再算出每个组的平均工资
select avg(sal) from emp
group by deptno
计算出公司支付给每个工种的总工资。
select sum(sal) from emp
group by job;
统计各部门的人数。
select count(*) from emp
group by deptno;
- group by 可以根据多个列来进行分组
比如 group by deptno,job
先根据部门号分组,同一个部门的,再根据职位分组
计算每个部门中每种工种各有多少职工数
思路:先根据部门号分组,同一个部门的,再根据职位分组,再算出他的count(*)
select deptno,job,count(*) from emp
group by deptno,job;
having 条件
having 也是对数据进行过滤和筛选,只不过是对分组后的内容进行的限制
如果使用了having就一定要使用group by
比如查询出部门人数大于3人的部门的部门号、部门人数以及部门的平均工资
select deptno,count(*),avg(sal) from emp
group by deptno
having count(*) > 3;
分组函数使用要点
- 分组函数只能出现在select、having、order by 子句中
- select中除了分组函数外的所有列名,必须出现在 group by 后面,否则,有语法错误(重要)
- 有having 一定有group by,但是有group by 不一定要有having
- 如果在select语句同时含有group by、having、order by,那么他们的顺序是group by、having、order by
练习
- 计算每个部门中每种工种各有多少职工数
- 查询各工种组的年平均工资,要求每个工种组至少在2人以上
- 查询出至少有两名秘书(CLERK)的所有部门的部门号,并按人数降序排序。
- 显示平均工资为>2000的职位
- 计算工资在2000以上,各种职位的平均工资大于3000的职位及平均工资
- 找每个部门的最高和最低的工资
- 找每个部门中每种职位的最高和最低的工资
- 显示出工作名称(job)中包含"MAN"的员工平均工资,最高工资,最低工资及工资的和
- 显示出20号部门的员工人数
- 显示出平均工资大于2000的部门号及平均工资
- 显示每个部门每种工作平均工资大于2500的部门及工作
- 显示出工作名称中包含"MAN",并且平均工资大于1000的工作名称及平均工资
- 列出最低工资大于1500的各种工作
多表查询
多表查询,如果查询的数据需要从多张表中获取,就需要在where字句后面,把这些表的相同含义的字段用等于号连接起来;
查找名字为"ALLEN"的职工所在的部门号、部门名和部门所在地
select e.ename,e.deptno,d.dname,d.loc from emp e,dept d
where e.deptno=d.deptno and e.ename='ALLEN';
练习
- 显示部门号为10的部门名(dname)、员工号和工资
- 查询部门号是20,30,40的职工的员工编号,姓名,工资,部门所在位置。
- 显示雇员名,雇员工资及所在的部门的名字,并按部门名排序
查询解题思路:
- 确定所查询的数据来自于哪些表;
- 如果查询的数据需要从多张表中获取,就需要在where字句后面,把这些表的相同含义的字段用等于号连接起来;
- 如果需要对单条数据做过滤,就把过滤条件追加到where字句后面,并用and连接起来;
- 如果需要对多组数据做统计,就要使用group by字句;
- 如果需要对分组后的数据做过滤,就要使用having字句;
- 如果需要排序,就要使用order by字句。
子查询
顾名思义,子查询就是在一个查询语句中嵌套使用了其他的查询语句
子查询,必须要用小括号括起来。
比如:查找出与“SMITH”在同一个部门工作的所有职工姓名及工资
select ename,sal from emp
where deptno = (SMITH的所在的部门号)
此时我们再写出sql语句,查找到SMITH的所在的部门号
select deptno from emp where ename='SMITH'
组合起来就是我们的子查询了
select ename,sal from emp
where deptno = (select deptno from emp where ename='SMITH')
注意如果子查询查询到了多个值,则就需要使用in/not in
例如:查找出部门10与部门30中工种相同的职工的姓名和工种。
select ename,job from emp
where deptno = 10 and job in(select disctinct(job) from emp where deptno = 30);
练习:
- 查找出工资比"SCOTT"工资高的职工的名字,工种,工资和所在的部门号,并按工资升序排序。
- 查找出工资比"SCOTT"高,并且在"NEW YORK"工作的职工的有关情况。
- 查找出具有最高月工资的雇员的姓名、工种和工资。
- 查找出在"CHICAGO"工作的职工的姓名、工种和工资。
- 查找出工资在1000到3500元之间的职工所在部门的所有人员的有关信息。
- 查找出工种在部门10中没有的其他部门职工的姓名、工种和工资信息。
- 查找出部门20中的工种相同的职工的姓名与工种。
- 查找出10号部门中的工种与销售部门中任何职工工种相同的职工的信息。
数据库扩展知识:
rowid
rowid:属于表中的列,是由数据库自动增加的列,是真实存在的一个列,唯一标识一条数据的物理位置
select rowid,e.ename from emp e;
rownum
rownum:是给结果集增加的一个序号,不属于任何的表,先有结果集,才能有rownum,始终是从1开始编号(不能跨过1而存在)
select rownum,e.ename,e.sal from emp;
from语句中使用子查询
比如:显示公司中工资最高的前三个用户的信息。
select a.ename,a.sal from (select ename,sal from emp order by sal desc) a where rownum <=3;
view视图
视图是一张虚拟表,其内容由查询定义,同真实的表一样,视图包含一系列带有名称的列和行数据。但是,视图并不在数据库中以存储的数据值集形式存在。行和列数据来自由定义视图的查询所引用的表,并且在引用视图时动态生成。
--创建视图
CREATE OR REPLACE VIEW my_view as ....
--删除视图
drop view my_view;
index.索引
索引用于提高查询效率
索引的内建工作对用户是透明的,由数据库自行维护,我们只需要指定是否添加索引。
索引是为表中字段添加的。当一个字段经常出现在WHERE中作为过滤条件,或 ORDER BY 或 DISTINCT中时可以为其添加索引以提高查询效率。
--创建索引
CREATE INDEX my_index
ON emp(ename)
--重建索引:如果经常在索引列上执行DML操作,需要定期重建索引
ALTER INDEX my_index REBUILD
--删除索引
DROP INDEX my_index
存储过程
存储过程,可简单理解为是由一组为了“完成特定功能”的SQL语句构成,经编译后存储在数据库中。
创建存储过程的语句如下:
CREATE [OR REPLACE] PROCEDURE <过程名>
<参数1>,「方式l]<数据类型1>,
<参数2>,[ 方式2]<数据类型2>,
……(定义变量)
IS|AS (is或as完全等价)
BEGIN
PL/SQL过程体
END;
例:
在emp表中,根据职工SCOTT的工种修改其工资,若工种为MANAGER,则工资加1000元,工种为SALESMAN,工资加800元,工种为ANALYST,工资加500元,否则工资加200元。
存储过程如下:
create or replace PROCEDURE modifySal
v_job emp.job%TYPE;
V_addsal emp.sal%TYPE;
BEGIN
select job into v_job from emp
where ename='SCOTT';
-----判断工种
if v_job = 'MANAGER' then
V_addsal := 1000;
elsif v_job = 'SALESMAN' then
V_addsal := 800;
elsif v_job = 'ANALYST' then
V_addsal := 500;
ELSE
V_addsal := 200;
END IF;
----- 修改工资
update emp
set sal = sal + v_addsal
where ename = 'SCOTT';
-----提交数据
COMMIT;
END;
备份表
备份结构与数据
create table 备份名 as select * from 表名;
仅备份结构
create table 备份名 as select * from 表名 where 1=2;