Oracle基本篇
函数实操这块,没有附带结果,因为结果粘贴出来截图会导致文章篇幅很长,大家可以自己编写SQL测试,也可以粘贴我的SQL进行测试(本人亲测都是可以查询出来的),本文有不当之处欢迎指正,也就是抛砖引入供大家参考学习,谢谢大家。
一、SQL大致分类
类别 | 语句 |
---|---|
数据定义语言(DDL):Data Definition Language | create、alter、drop、truncate |
数据操作语言(DML):Data Manipulation Language | insert、update、delete |
数据查询语言(DQL):Data Query Language | select |
事务控制语言(TCL):Transaction Control Language | commit、rollback、savepoint |
数据控制语言(Data Control Language) | grant、revoke、create user |
1. 数据定义语言(DDL):Data Definition Language
CREATE TABLE: 用于创建表
CREATE TABLE TableNAME(
columName1 dataType,
columName2 dataType,
columName3 dataType,
......
)
ALTER TABLE:用于对已有的表中添加、修改或者删除
ALTER TABLE TableName ADD columName dataType;
ALTER TABLE TableName DROP columName;
ALTER TABLE tableName MODIFY(columName dataType);
2. 数据操纵语言(DML):Data Manipulation Language
INSERT: 新增数据
INSERT INTO TableName(columName1,columName2...) VALUES (value1,value2...);
UPDATE: 更新数据
UPDATE TabelName SET columName1=value1,columName2=value2... WHERE 条件;
DELETE: 删除数据
DELETE FROM TableName WHERE 条件;
3. 数据查询语言(DQL):Data Query Language
SELECT: 查询数据
// 查询所有列
SELECT * FROM TableName;
// 条件查询
SELECT * FROM TabelName WHERE 条件;
..........
4. 事务控制语言(TCL):Transaction Control Language
用来维护数据一致性的语句
COMMIT:提交,确认已经进行的数据改变
ROLLBACK:回滚,取消已经进行的数据改变
SAVEPOINT:保存点,使当前的事务可以回退到指定的保存点,便于取消部分改变
5. 数据控制语言(Data Control Language)
用于执行权限的授予和收回操作
GRANT:授予,用于给用户或角色授予权限
REVOKE:用于收回用户或角色已有的权限
CREATE USER:创建用户
二、数据类型
列举实际工作中最常见的三种数据类型,还有char:固定字符串,TIMESTAMP:时间,CLOB:大文本,BLOB:二进制。
类型 | 详情 |
---|---|
NUMBER(p,s) | 数字类型,可以存储整数,也可以是浮点数,还有FlOAT/DOUBLE/INT, p表示数字的最大位数(如果是小数包括整数部分和小数部分和小数点,p默认是38为, s是指小数位数。 |
VARCHAR2(length) | 存储可变长度的字符串。length指定了该字符串的最大长度。默认长度是1,最长不超过4000字符。 |
DATE | 存储日期和时间,存储纪元、4位年、月、日、时、分、秒,存储时间从公元前4712年1月1日到公元后4712年12月31日。 |
三、序列的使用
// 创建序列
CREATE sequence sequenceName;
// 查询下一个值
SELECT sequenceName.nextval FROM dual;
// 查询当前值
SELECT sequenceName.currval FROM dual;
四、常用函数
演示数据来自于Oracle数据库SCOTT用户的员工表
1. 大小写函数
select upper(e.job) from emp e;
select lower(e.job) from emp e;
2. 数值函数
select round(e.sal,2) from emp e; -- 四舍五入,后面的参数表示小数点后保留的位数
select trunc(e.sal,2) from emp e; -- 直接截取,不在看后面位数的数字
select mod(10,2) from dual; -- 求余
3. 日期函数
-- 查询emp表所有员工入职距离现在多少天
select round(sysdate-hiredate,2) from emp;
select sysdate-hiredate from emp;
-- 算出明天此刻时间
select hiredate+1 from emp;
-- 查询emp表中所有员工入职距离现在几个月
select months_between(sysdate,hiredate) from emp;
-- 查询emp表中所有员工入职距离现在几年
select months_between(sysdate,hiredate)/12 from emp;
-- 查询emp表中所有员工入职距离现在几周
select round((sysdate-hiredate)/7,2) from emp;
4. 转换函数
-- 日期转字符串
select to_char(hiredate,'yyyy-mm-dd hh24:mi:ss') from emp;
-- 字符串转日期
select to_date('1980-12-17 16:39:50','yyyy-mm-dd hh24:mi:ss') from dual;
5. 通用函数
Oracle中null与任意数字做算术,都为null
select ename,sal+nvl(comm,0) from emp;
6. 条件判断
Oracle中除了取别名用双引号,其他均用单引号
通用用法:
--- 等值条件判断
select e.ename,
case e.ename
when 'SMITH' then '史密斯'
when 'ALLEN' then '艾伦'
when 'JONES' then '约翰'
else '无名'
end "中文名"
from emp e;
--- 范围条件判断
select e.sal,
case
when e.sal>3000 then '高收入'
when e.sal>1500 then '中收入'
else '低收入'
end "收入等级"
from emp e;
Oracle专用用法:
select e.ename,
decode( e.ename,
'SMITH', '史密斯',
'ALLEN', '艾伦',
'JONES', '约翰',
'无名') "中文名"
from emp e;
7. 多行函数
select count(1)from emp e; -- 统计
select max(e.sal)from emp e; -- 最大
select min(e.sal)from emp e; -- 最小
select sum(e.sal)from emp e; -- 求和
select avg(e.sal)from emp e; -- 平均
8. 分组查询
分组查询中,出现在group by 后面的原始列才能出现在select后面,没有出现在group by后面的原始列想要在select后面,必须使用聚合函数
-- 查询每个部门的平均工资
select e.deptno,avg(e.sal),--e.ename
from emp e
group by e.deptno;
-- 查询出平均工资高于2000的部门
select e.deptno,avg(e.sal)
from emp e
group by e.deptno
having avg(e.sal)>2000;
-- 查询出每个部门工资高于800的员工的平均工资
select e.deptno,avg(e.sal)
from emp e
where e.sal>800
group by e.deptno;
-- 查询出每个部门工资高于800的员工的平均工资,然后平均工资高于2000的部门
select e.deptno,avg(e.sal)
from emp e
where e.sal>800
group by e.deptno
having in avg(e.sal)>2000;
where是过滤分组前的数据,having是过滤分组后的数据。
表现形式:where必须在group by之前,having是在group by之后。
9. 多表查询
内连接 inner join on:也叫等值查询,会产生笛卡尔积
select * from emp e;
-- 等值查询
select *
from emp e, dept d
where e.deptno = d.deptno;
-- inner join on
select *
from emp e
inner join dept d
on e.deptno = d.deptno;
外连接,分为左外连接和右外连接
-- 左外连接
select *
from emp e
left join dept d
on e.deptno = d.deptno;
-- 右外连接
select *
from emp e
right join dept d
on e.deptno = d.deptno;
Oracle专用: +号在哪边,就以另外一个表为主表
select *
from emp e, dept d
where e.deptno(+) = d.deptno;
自连接:其实就是站在不同的角度多一张表看成多张表
-- 查询出员工姓名,员工领导姓名
select e1.ename, e2.ename
from emp e1,emp e2
where e1.mgr = e2.empno
-- 查询出员工姓名,员工部门名称,员工领导姓名,员工领导部门名称
select e1.ename,d1.dname, e2.ename, d2.dname
from emp e1,emp e2,dept d1, dept d2
where e1.mgr = e2.empno
and e1.deptno =d1.deptno
and e2.deptno =d2.deptno;
10. 子查询
-- 查询出每个部门最低工资,和最低工资员工姓名,和该员工所在部门名称
select t.deptno,t.msal,e.ename,d.deptno
from
(select deptno, min(sal) msal
from emp
group by deptno )t,emp e, dept d
where t.deptno = e.deptno
and t.msal = e.sal
and e.deptno = d.deptno;
11. 分页查询
rownum行号:当我们做select查询的时候,没查询出一条记录,就会在该条记录前加一个行号,行号从1开始,一次递增,不能跳着走
select rownum, e.*
from emp e
order by e.sal
desc
五、视图
什么是视图:视图就是提供一个查询的窗口,所有的数据来源与原表。
视图的作用:
- 可以有效避免敏感字段,如工资。
- 可以保证数据及时统一,如库存。
-- 创建视图:
-- 跨用户查询
create view v_emp as select empno,ename,job,deptno from 用户.表明 with read only;
-- 从本库创建视图
create view v_emp as select empno,ename,job,deptno from emp with read only;
select * from v_emp; -- 查询视图
update v_emp set JOB = 'CLERK' where ename='ALLEN'; -- 修改视图 [不推荐]
commit;
创建视图要有dba权限,创建视图报警无权限窗口的解决办法:
赋予用户创建视图的权限:GRANT CREATE VIEW TO 用户;
赋予可以查询任何表的权限:GRANT SELECT ANY TABLE TO 用户;
赋予可以查询任何字典的权限:GRANT SELECT ANY DICTIONARY TO 用户;
六、索引
什么是索引?
索引就是在表的列上构建一个二叉树,达到大幅度提高查询效率的目的,同时也会降低增删改的效率。
1. 单列索引
-- 创建单列索引
create index idx_ename on emp(ename);
select * from emp where ename = 'SCOTT';
单列索引触发规则:条件必须是索引列中的原始值,单行函数、模糊查询都会影响索引的出发。
2. 复合索引
-- 创建复合索引
create index idx_ename_job on emp(ename,job);
复合索引触发规则:第一列为优先检索列,如果要触发复合索引,必须包含有优先检索列中的原始值。
select * from emp where ename = 'SCOTT' and job ='xx'; -- 触发复合索引
select * from emp where ename = 'SCOTT' or job ='xx'; -- 不触发复合索引
select * from emp where ename = 'SCOTT'; -- 既有单列索引又有复合索引,触发单列索引
7、简单sql练习
1. select * from
-- 查看视图
select * from v_emp;
-- 查看scott用户下所有的对象
select * from tab;
-- 查询emp表的员工编号,姓名,工资,部门号,列名,大小写不敏感,但提倡大写
select e.empno "员工编号",
e.ename "姓名",
e.sal "工资",
e.deptno "部门号",
e.comm "奖金"
from emp e;
-- 查询emp表的不重复的工作
select distinct job from emp;
-- 查询员工的编号,姓名,月薪,年薪(月薪*12)
select e.empno "员工编号",
e.ename "姓名",
e.sal "月薪",
e.sal*12 "年薪"
from emp e;
-- 查询员工的编号,姓名,入职时间,月薪,年薪,年收入(年薪+奖金)
select e.empno "员工编号",
e.ename "姓名",
e.hiredate "入职时间",
e.sal "月薪",
e.sal*12 "年薪",
e.sal*12+nvl(e.comm,0) "年收入" -- Oracle中null做算数运算,都为null,使用通用函数NVL(a,b) 当a不为null时使用a,为null使用b
from emp e;
-- 伪表的使用
select 'hello' || ' world' "结果" from dual;
-- sysdate时间
select sysdate from dual;
2. where 条件的使用
-- 除了别名是双引号,其他都是单引号,字符串大小写敏感
select * from emp where ename = 'SMITH'; -- 写smith就查询不出来结果
-- 查询1980年12月17日入职的员工,to_date()日期转换
select *
from emp
where hiredate = to_date('1980-12-17', 'yyyy-mm-dd hh-mi-ss');
-- 查询工资大于1500的员工
select * from emp where sal > 1500;
-- 查询工资不等于1500的员工【!=或<>】
select * from emp where sal <> 1500;
-- 查询薪水在1300到1600之间的员工,包括1300和1600
select * from emp where sal between 1300 and 1600;
-- 查询薪水不在1300到1600之间的员工,不包括1300和1600
select * from emp where sal NOT between 1300 and 1600;
-- 查询入职时间在"1981-2月-20"到"1982-1月-23"之间的员工
select *
from emp
where hiredate between to_date('1981-02-20', 'yyyy-mm-dd') and
to_date('1982-01-23', 'yyyy-mm-dd');
-- 查询20号或30号部门的员工,例如:根据ID号,选中的员工,批量删除
select * from emp where deptno in (20, 30);
-- 查询不是20号或30号部门的员工
select * from emp where deptno not in (20, 30);
3. 多行函数,group by、having
-- 统计emp表中员工总人数
select count(*) from emp;
-- *号适用于表字段较少的情况下,如果字段较多,扫描多间多,效率低,项目中提倡使用某一个非null唯一的字段,通常是主键
-- 统计公司有多少个不重复的部门
select count(distinct deptno) from emp;
-- 统计有佣金的员工人数
select count(comm) from emp;
-- 注意:今天讲的这些多个行函数,不统计NULL值
-- 员工总工资,平均工资,四舍五入,保留小数点后0位
select sum(sal) "总工资", round(avg(sal), 0) "平均工资" from emp;
-- 查询员工表中最高工资,最低工资
select max(sal) "最高工资", min(sal) "最低工资" from emp;
-- 入职最早,入职最晚员工
select max(hiredate) "最晚入职时间", min(hiredate) "最早入职时间" from emp;
-- 按部门求出该部门平均工资,且平均工资取整数,采用截断
select deptno "部门编号", trunc(avg(sal), 0) "部门平均工资"
from emp
group by deptno;
-- (继续)查询部门平均工资大于2000元的部门
select deptno "部门编号", trunc(avg(sal), 0) "部门平均工资"
from emp
group by deptno
having trunc(avg(sal), 0) > 2000;
-- (继续)按部门平均工资降序排列
select deptno "部门编号", trunc(avg(sal), 0) "部门平均工资"
from emp
group by deptno
having trunc(avg(sal), 0) > 2000
order by 2 desc;
-- 除10号部门外,查询部门平均工资大于2000元的部门,方式一【having deptno<>10】
select deptno, avg(sal) from emp group by deptno having deptno <> 10;
-- 除10号部门外,查询部门平均工资大于2000元的部门,方式二【where deptno<>10】
select deptno, avg(sal) from emp where deptno <> 10 group by deptno;