oracle基础
来源:互联网 发布:软件 程序员 编写 编辑:程序博客网 时间:2024/05/20 02:25
引言:oracle的最基础是件很容易的事情,但性能优化和表结构设计却绝不是一件容易的事
一.Oracle中常用增删改查操作
以scott用户
SQL> --当前用户
SQL> show user
SQL> --当前用户下的表
SQL> select * from tab;
SQL> --员工表的结构
SQL> desc emp
SQL> --清屏
SQL> host cls
SQL> --查询所有的员工信息
SQL> select * from emp;
SQL> --设置行宽
SQL> show linesize
linesize 80
SQL> set linesize 120
SQL> --设置列宽
SQL> col ename for a8
SQL> col sal for 9999
SQL> --查询员工信息:员工号 姓名 月薪
SQL> select empno,ename,sal
2 form emp;
form emp
*
第 2 行出现错误:
ORA-00923: 未找到要求的 FROM 关键字
SQL> --c命令 change
SQL> 2
2* form emp
SQL> c /form/from --将form替换为from
2* from emp
SQL> /*
SQL> SQL中的null
SQL> 1、包含null的表达式都为null
SQL> 2、null永远!=null
SQL> */
SQL> --nvl(a,b) nvl2 nvl(null,0) 当为null值返回0 nvl2(a,b,c) 当为a为空值返回c,否则返回b
SQL> select empno,ename,sal,sal*12,comm,sal*12+nvl(comm,0)
2 from emp;
null永远!=null
SQL> --distinct 去掉重复记录
SQL> select deptno from emp;
--concat函数 dual为虚表.mysql在5.0以后也有
select 'Hello'||' World' 字符串 from dual;
SQL> --查询员工信息:***的薪水是****
SQL> select ename||'的薪水是'||sal 信息 from emp;
SQL> --null值 3、如果集合中含有null,不能使用not in;但可以使用in
SQL> ed
已写入 file afiedt.buf
1 select *
2 from emp
3* where deptno not in (10,20,null)
SQL> --转意字符
SQL> ed
已写入 file afiedt.buf
1 select *
2 from emp
3* where ename like '%\_%' escape '\' ---用于查询名称中带_ 如ename 为 name_wpx的字段
--原因:null值最大 ,涉及null值的排序
1 select *
2 from emp
3 order by comm desc
4* nulls last
--oracle分页(Pageing Query)
=
select *
from (select rownum r,e1.*
from (select * from emp order by sal) e1
where rownum <=8
)
where r >=5;
SQL> /*
SQL> SQL的类型
SQL> 1、DML(Data Manipulation Language 数据操作语言): select insert update delete
SQL> 2、DDL(Data Definition Language 数据定义语言): create table,alter table,truncate table,drop table
SQL> create/drop view,sequnece,index,synonym(同义词)
SQL> 3、DCL(Data Control Language 数据控制语言): grant(授权) revoke(撤销权限)
SQL> */
SQL> --插入insert
oracle的插入类似于原生jdbc的PreparedStatement,或者说类似于mybatis的Statement
SQL> --PreparedStatement pst = "insert into emp(empno,ename,sal,deptno) values(?,?,?,?)";
SQL> --地址符 &
SQL> insert into emp(empno,ename,sal,deptno) values(&empno,&ename,&sal,&deptno);
输入 empno 的值: 1002
输入 ename 的值: 'Mary'
输入 sal 的值: 2000
输入 deptno 的值: 20
原值 1: insert into emp(empno,ename,sal,deptno) values(&empno,&ename,&sal,&deptno)
新值 1: insert into emp(empno,ename,sal,deptno) values(1002,'Mary',2000,20)
当然你在要查询的字段也可这么设置
SQL> select empno,ename,sal,&t
2 from emp;
输入 t 的值: job
SQL> --一次性将emp中,所有10号部门的员工插入到emp10中
SQL> insert into emp10 select * from emp where deptno=10;
SQL> /*
SQL> 海量插入数据:
SQL> 1、数据泵(PLSQL程序)
SQL> dbms_datapump(程序包)
SQL> 2、SQL*Loader
SQL> 3、外部表
SQL> */
SQL> host cls
SQL> /*
SQL> delete和truncate的区别
SQL> 1、delete逐条删除;truncate先摧毁表 再重建2
SQL> 2、(*)delete是DML truncate是DDL
SQL> (可以回滚) (不可以回滚)
SQL> 3、delete不会释放空间 truncate会
SQL> 4、delete会产生碎片 truncate不会
SQL> 5、delete可以闪回(flashback) truncate不可以
/*
SQL> Oracle中的事务
SQL> 1、起始标志: 事务中的第一条DML语句
SQL> 2、结束标志:提交: 显式 commit 隐式: 正常退出 DDL DCL
SQL> 回滚: 显式 rollback 隐式: 非正常退出 掉电 宕机
SQL> */
SQL> savepoint a; SQL> rollback to savepoint a;
SQL> set transaction read only;
二.函数类
1.单行函数
SQL> --字符函数
SQL> select lower('Hello Wpx') 转小写,upper('Hello Wpx') 转大写,initcap('hello wpx') 首字母大写
2 from dual;
SQL> --substr(a,b) 从a中,第b位开始取
SQL> --substr(a,b,c) 从a中,第b位开始取,取c位
SQL> --length 字符数 lengthb 字节数
SQL> --instr(a,b)
SQL> --在a中,查找b
SQL> --lpad 左填充 rpad 右填充
SQL> -- abcd ---> 10位
SQL> select lpad('abcd',10,'*') 左,rpad('abcd',10,'*') 右 from dual;
SQL> --trim 去掉前后指定的字符
SQL> select trim('H' from 'Hello WorldH') from dual;
SQL> --replace He**o Wor*d 将字符中的l替换为*
SQL> select replace('Hello World','l','*') from dual;
SQL> --四舍五入 45.93 45.9 46 50 0
SQL> select round(45.926,2) 一,round(45.926,1) 二,round(45.926,0) 三,round(45.926,-1) 四,round(45.926,-2) 五
2 from dual;
SQL> --截断 45.92 45.9 45 40 0
1 select trunc(45.926,2) 一,trunc(45.926,1) 二,trunc(45.926,0) 三,trunc(45.926,-1) 四,trunc(45.926,-2) 五
2* from dual
日期类常用转化
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual;
SQL> --昨天 今天 明天
SQL> select (sysdate-1) 昨天,sysdate 今天,(sysdate+1) 明天
2 from dual;
SQL> --计算员工的工龄:天 星期 月 年
SQL> select ename,hiredate,(sysdate-hiredate) 天,(sysdate-hiredate)/7 星期,
2 (sysdate-hiredate)/30 月,(sysdate-hiredate)/365 年
3 from emp;
SQL> --months_between
SQL> select ename,hiredate,(sysdate-hiredate)/30 一,months_between(sysdate,hiredate) 二
2 from emp;
SQL> --查询员工的薪水:两位小数、千位符、本地货币代码
SQL> select to_char(sal,'L9,999.99') from emp;
SQL> select comm,sal,coalesce(comm,sal) "第一个不为null的值"
2 from emp;
SQL> select ename,job,sal 涨前,
2 case job when 'PRESIDENT' then sal+1000
3 when 'MANAGER' then sal+800
4 else sal+400
5 end 涨后
6 from emp;
SQL> select ename,job,sal 涨前,
2 decode(job,'PRESIDENT',sal+1000,
3 'MANAGER',sal+800,
4 sal+400) 涨后
5 from emp;
2.2多行函数SQL> --工资总额
SQL> select sum(sal) from emp;
SQL> --人数
SQL> select count(*) from emp;
SQL> --平均工资
SQL> select sum(sal)/count(*) 一,avg(sal) 二 from emp;
SQL> --null值 组函数会自动滤空; count(comm) 14
SQL> select count(*), count(nvl(comm,0)) from emp; --15
SQL> --多个列的分组
SQL> select deptno,job,sum(sal)
2 from emp
3 group by deptno,job
4 order by 1;
SQL> --多个列的分组: 先按照第一个列分组,如果相同,再第二个列分组,以此类推
SQL> --查询平均工资大于2000的部门
SQL> select deptno,avg(sal)
2 from emp
3 group by deptno
4 having avg(sal) > 2000;
SQL> --where和having的区别:where不能使用多行函数
SQL> --查询10号部门的平均工资
SQL> select deptno,avg(sal)
2 from emp
3 group by deptno
4 having deptno=10;
使用oracle的增强group by做报表
SQL> break on deptno skip 2 --美化
SQL> select deptno,job,sum(sal) from emp group by rollup(deptno,job);
三.多表查询
常用公式:select 要查询的内容 from 要查询的位置 where 消笛卡尔积 + 查询条件
上述文字部分可由其他查询条件替代
SQL> --等值连接
SQL> select e.empno,e.ename,e.sal,d.dname
2 from emp e,dept d
3 where e.deptno=d.deptno;
SQL> --不等值连接
SQL> --查询员工信息:员工号 姓名 月薪 工资级别
SQL> select e.empno,e.ename,e.sal,s.grade
2 from emp e,salgrade s
3 where e.sal between s.losal and s.hisal;
SQL> --外连接:
SQL> --按部门统计员工信息:部门号 部门名称 人数
SQL> select d.deptno 部门号,d.dname 部门名称,count(e.empno) 人数
2 from emp e,dept d
3 where e.deptno=d.deptno
4 group by d.deptno,d.dname;
SQL> /*
SQL> 希望把某些不成立的记录(40号部门),任然包含在最后的结果中 ---> 外连接
SQL> 左外连接: 当where e.deptno=d.deptno不成立的时候,等号左边的表任然被包含在最后的结果中
SQL> 写法:where e.deptno=d.deptno(+)
SQL> 右外连接: 当where e.deptno=d.deptno不成立的时候,等号右边的表任然被包含在最后的结果中
SQL> 写法:where e.deptno(+)=d.deptno
SQL> */
SQL> select d.deptno 部门号,d.dname 部门名称,count(e.empno) 人数
2 from emp e,dept d
3 where e.deptno(+)=d.deptno
4 group by d.deptno,d.dname;
SQL> --自连接: 通过表的别名,将同一张表视为多张表
SQL> select e.ename 员工姓名,b.ename 老板姓名
2 from emp e,emp b
3 where e.mgr=b.empno;
SQL> --自连接不适合操作大表
SQL> --层次查询
SQL> select level,empno,ename,mgr
2 from emp
3 connect by prior empno=mgr
4 start with mgr is null
5 order by 1;
子查询
SQL> --子查询所要解决的问题:不能一步求解
SQL> select *
2 from emp
3 where sal > (select sal
4 from emp
5 where ename='SCOTT');
SQL> /*
SQL> 注意的问题:1
SQL> 1、括号
SQL> 2、合理的书写风格
SQL> 3、可以在主查询的where select having from 后面使用子查询
SQL> 4、不可以在group by使用子查询
SQL> 5、强调from后面的子查询
SQL> 6、主查询和子查询可以不是同一张表;只有子查询返回的结果 主查询可以使用 即可
SQL> 7、一般不在子查询中排序;但在top-n分析问题中 必须对子查询排序
SQL> 8、一般先执行子查询,再执行主查询;但相关子查询例外
SQL> 9、单行子查询只能使用单行操作符;多行子查询只能使用多行操作符
SQL> 10、子查询中的null
SQL> */
SQL> --可以在主查询的where select having from 后面使用子查询
SQL> select empno,ename,sal,(select job from emp where empno=7839) 第四列
2 from emp;
SQL> --查询员工信息:员工号 姓名 月薪
SQL> select *
2 from (select empno,ename,sal from emp);
主查询和子查询可以不是同一张表;只有子查询返回的结果 主查询可以使用 即可
SQL> --查询部门名称是SALES的员工
SQL> select *
2 from emp
3 where deptno=(select deptno from dept where dname='SALES');
SQL> --SQL优化 3、尽量使用多表查询
SQL> --SQL执行计划
SQL> host cls
SQL> --in 在集合中
SQL> --查询部门名称是SALES和ACCOUNTING的员工
SQL> select *
2 from emp
3 where deptno in (select deptno from dept where dname='SALES' or dname='ACCOUNTING');
SQL> select e.*
2 from emp e,dept d
3 where e.deptno=d.deptno and (d.dname='SALES' or d.dname='ACCOUNTING');
SQL> --any: 和集合中的任意一个值比较
SQL> --查询工资比30号部门任意一个员工高的员工信息
SQL> select *
2 from emp
3 where sal > any (select sal from emp where deptno=30);
1 select *
2 from emp
3* where sal > (select min(sal) from emp where deptno=30)
SQL> select *
2 from emp
3 where empno not in (select mgr from emp);
未选定行
SQL> --查询是老板的员工信息
SQL> ed
已写入 file afiedt.buf
1 select *
2 from emp
3* where empno in (select mgr from emp)
SQL> select *
2 from emp
3 where empno not in (select mgr from emp where mgr is not null);
四.创建管理表
SQL> --rowid 行地址
SQL> select rowid,empno,ename,sal from emp;
SQL> create table emp20
2 as
3 select * from emp where deptno=20;
SQL> --修改表:增加新列,修改列,删除列,重命名列,重命名表
SQL> --增加新列
SQL> alter table test1 add photo blob;
SQL> --修改列
SQL> alter table test1 modify tname varchar2(40);
SQL> --删除列
SQL> alter table test1 drop column photo;
SQL> --重命名列
SQL> alter table test1 rename column tname to username;
SQL> --重命名表
SQL> rename test1 to test2;
SQL> --查看回收站
SQL> show recyclebin;
SQL> --清空回收站
SQL> purge recyclebin;
SQL> --注意:管理员没有回收站
五.简单pl
--打印Hello World
declare
--说明部分
begin
--程序
dbms_output.put_line('Hello World');
end;
实际上,一个plsql还应该有Exception部分
if 判断
-- 判断用户从键盘输入的数字--接受键盘输入--变量num:是一个地址值,在该地址上保存了输入的值accept num prompt '请输入一个数字';declare --定义变量保存输入 的数字 pnum number := #begin if pnum = 0 then dbms_output.put_line('您输入的是0'); elsif pnum = 1 then dbms_output.put_line('您输入的是1'); elsif pnum = 2 then dbms_output.put_line('您输入的是2'); else dbms_output.put_line('其他数字'); end if;end;
-- 打印1~10declare -- 定义变量 pnum number := 1;begin loop --退休条件 exit when pnum > 10; --打印 dbms_output.put_line(pnum); --加一 pnum := pnum + 1; end loop;end;
--记录型变量: 查询并打印7839的姓名和薪水declare --定义记录型变量:代表一行 emp_rec emp%rowtype;begin select * into emp_rec from emp where empno=7839; dbms_output.put_line(emp_rec.ename||'的薪水是'||emp_rec.sal);end;
--引用型变量: 查询并打印7839的姓名和薪水declare --定义变量保存姓名和薪水 --pename varchar2(20); --psal number; pename emp.ename%type; psal emp.sal%type;begin --得到7839的姓名和薪水 select ename,sal into pename,psal from emp where empno=7839; --打印 dbms_output.put_line(pename||'的薪水是'||psal);end;
系统异常
-- 被0除declare pnum number;begin pnum := 1/0; exception when zero_divide then dbms_output.put_line('1:0不能做分母'); dbms_output.put_line('2:0不能做分母'); when value_error then dbms_output.put_line('算术或者转换错误'); when others then dbms_output.put_line('其他例外');end;
-- 查询50号部门的员工declare cursor cemp is select ename from emp where deptno=50; pename emp.ename%type; --自定义例外 no_emp_found exception;begin open cemp; --取第一条记录 fetch cemp into pename; if cemp%notfound then --抛出例外 raise no_emp_found; end if; --进程:pmon进程(proccesss monitor) close cemp;exception when no_emp_found then dbms_output.put_line('没有找到员工'); when others then dbms_output.put_line('其他例外');end;
-- 查询并打印员工的姓名和薪水/*光标的属性: %isopen %rowcount(影响的行数) %found %notfound*/declare --定义光标(游标) cursor cemp is select ename,sal from emp; pename emp.ename%type; psal emp.sal%type;begin --打开 open cemp; loop --取当前记录 fetch cemp into pename,psal; --exit when 没有取到记录; exit when cemp%notfound; dbms_output.put_line(pename||'的薪水是'||psal); end loop; --关闭 close cemp;end;
例一
/*1、SQL语句select to_char(hiredate,'yyyy') from emp;---> 集合 ---> 光标 ---> 循环---> 退出: notfound2、变量:(*)初始值 (*)最终如何得到每年入职的人数count80 number := 0;count81 number := 0;count82 number := 0;count87 number := 0;*/declare --定义光标 cursor cemp is select to_char(hiredate,'yyyy') from emp; phiredate varchar2(4); --每年入职的人数 count80 number := 0; count81 number := 0; count82 number := 0; count87 number := 0;begin --打开光标 open cemp; loop --取一个员工的入职年份 fetch cemp into phiredate; exit when cemp%notfound; --判断年份是哪一年 if phiredate = '1980' then count80:=count80+1; elsif phiredate = '1981' then count81:=count81+1; elsif phiredate = '1982' then count82:=count82+1; else count87:=count87+1; end if; end loop; --关闭光标 close cemp; --输出 dbms_output.put_line('Total:'||(count80+count81+count82+count87)); dbms_output.put_line('1980:'|| count80); dbms_output.put_line('1981:'|| count81); dbms_output.put_line('1982:'|| count82); dbms_output.put_line('1987:'|| count87);end;
/*1、SQL语句selet empno,sal from emp order by sal;---> 光标 ---> 循环 ---> 退出:1. 总额>5w 2. notfound2、变量:(*)初始值 (*)最终如何得到涨工资的人数: countEmp number := 0;涨后的工资总额:salTotal number;(1)select sum(sal) into salTotal from emp;(2)涨后=涨前 + sal *0.1练习: 人数:8 总额:50205.325*/declare cursor cemp is select empno,sal from emp order by sal; pempno emp.empno%type; psal emp.sal%type; --涨工资的人数: countEmp number := 0; --涨后的工资总额: salTotal number;begin --得到工资总额的初始值 select sum(sal) into salTotal from emp; open cemp; loop -- 1. 总额 >5w exit when salTotal > 50000; --取一个员工 fetch cemp into pempno,psal; --2. notfound exit when cemp%notfound; --涨工资 update emp set sal=sal*1.1 where empno=pempno; --人数+1 countEmp := countEmp +1; --涨后=涨前 + sal *0.1 salTotal := salTotal + psal * 0.1; end loop; close cemp; commit; dbms_output.put_line('人数:'||countEmp||' 总额:'||salTotal);end;
/*1、SQL语句部门:select deptno from dept; ---> 光标部门中员工的薪水: select sal from emp where deptno=?? ---> 带参数的光标2、变量:(*)初始值 (*)最终如何得到每个段的人数count1 number; count2 number; count3 number;部门的工资总额salTotal number := 0;(1)select sum(sal) into salTotal from emp where deptno=??(2)累加*/declare --部门 cursor cdept is select deptno from dept; pdeptno dept.deptno%type; --部门中员工的薪水 cursor cemp(dno number) is select sal from emp where deptno=dno; psal emp.sal%type; --每个段的人数 count1 number; count2 number; count3 number; --部门的工资总额 salTotal number := 0;begin --部门 open cdept; loop --取一个部门 fetch cdept into pdeptno; exit when cdept%notfound; --初始化 count1:=0; count2:=0; count3:=0; --得到部门的工资总额 select sum(sal) into salTotal from emp where deptno=pdeptno; --取部门的中员工薪水 open cemp(pdeptno); loop --取一个员工的薪水 fetch cemp into psal; exit when cemp%notfound; --判断 if psal < 3000 then count1:=count1+1; elsif psal >=3000 and psal<6000 then count2:=count2+1; else count3:=count3+1; end if; end loop; close cemp; --保存结果 insert into msg values(pdeptno,count1,count2,count3,nvl(saltotal,0)); end loop; close cdept; commit; dbms_output.put_line('完成'); end;
每当成功插入新员工后,自动打印“成功插入新员工”
create trigger firsttrigger
after insert
on emp
declare
begin
dbms_output.put_line('成功插入新员工');
end;
- oracle基础
- Oracle基础
- oracle基础
- Oracle基础
- oracle基础
- Oracle 基础
- oracle 基础
- Oracle基础
- oracle基础
- oracle基础
- oracle基础
- oracle基础
- Oracle 基础
- Oracle基础
- oracle基础
- oracle基础
- Oracle基础
- Oracle基础
- 通过METAMASK调试和发布智能合约指南》
- python几种编译器使用
- PID控制的MATLAB仿真(1)
- 0.96寸OLED屏使用详解
- stomp over websocket协议原理与实现
- oracle基础
- 一张图理解String字符串
- [POJ](2524)Ubiquitous Religions ---- 并查集
- Kubernetes最小集群配置
- ARM 嵌入式微处理器指令集(下)
- 基于JSON+JQuery实现的多条件筛选功能(类似京东和淘宝功能)
- C# (ref)值传递转成引用传递
- Docker 加速
- C/C++_关于rand()和srand()的调用方式的一点探究