一.输出程序
declare
--说明部分
begin
--程序
dbms_output.put_line('Hello World');
end;
打开输出开关:set serveroutput on
二.pl/sql程序
0.从键盘输入
accept num prompt ‘请输入一个数字’;
1.引用型变量
declare
--定义变量保存姓名和薪水
pname emp.ename%type;
psal emp.sal%type;
begin
select ename,sal into pname,psal from emp where empno=7839;
dbms_output.put_line(pname||'的薪水'||psal);
end;
2.记录型变量
declare
emp_rec emp%rowtype;
begin
select * into emp_rec from emp where emp.empno=7839;
dbms_output.put_line(emp_rec.ename||'的薪水'||emp_rec.sal);
end;
三.条件语句
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~10
declare
pnum number := 1;
begin
loop
--循环 --退出条件
exit when pnum > 10;
dbms_output.put_line(pnum);
--加一
pnum := pnum + 1;
end loop;
end;
declare
pnum number :=1;
begin
for pnum in 1..9
loop
dbms_output.put_line(pnum);
end loop;
end;
五.光标
光标的属性:
%isopen //判断光标是否打开,打开返回true
%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;
-- 查询某个部门的员工姓名
declare
cursor cemp(dno number) is select ename from emp where deptno=dno;
pename emp.ename%type;
begin
open cemp(20);
loop
fetch cemp into pename;
exit when cemp%notfound;
dbms_output.put_line(pename);
end loop;
close cemp;
end;
-- 涨工资,总裁1000 经理800 其他400
declare
-- 定义光标
cursor cemp is select empno,job from emp;
pempno emp.empno%type;
pjob emp.job%type;
begin
rollback;
--打开光标
open cemp;
loop
--取一个员工
fetch cemp into pempno,pjob;
exit when cemp%notfound;
--判断职位
if pjob = 'PRESIDENT' then update emp set sal=sal+1000 where empno=pempno;
elsif pjob = 'MANAGER' then update emp set sal=sal+800 where empno=pempno;
else update emp set sal=sal+400 where empno=pempno;
end if;
end loop;
--关闭光标
close cemp;
--提交 ---> ACID
commit;
dbms_output.put_line('完成');
end;
六.Oracle的异常处理
1.系统定义的例外
not_data_found (没有找到数据)
too_many_rows (select..into语句匹配多个行)
zero_divide(被零除)
value_error(算术或转换错误)
timeout_on_resource(在等待资源时发生超时)
2.用户定义的例外
-- 查询50号部门的员工姓名
declare
--定义光标:代表50号部门的员工
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进程: process monitor
close cemp;
exception
when no_emp_found then dbms_output.put_line('没有找到员工');
when others then dbms_output.put_line('其他例外');
end;
/
3.进程监视器进程(PMON)
在用户进程失败时(产生异常)执行进程恢复
–清除数据库缓冲区高速缓存
–释放该用户进程使用的资源
七.相关实例
实例一.统计每年入职的员工人数
/*
SQL语句
select to_char(hiredate,'yyyy') from emp;
--->光标 --> 循环 --> 退出条件:notfound
变量:1. 初始值 2.最终得到
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;
实例二.为员工涨工资。从最低工资涨起每人涨10%,但工资总额不能超过5万元, 请计算涨工资的人数和涨工资后的工资总额,并输出涨工资人数及工资总额。
/*分析
SQL语句
select empno,sal from emp order by sal;
–>光标–> 循环 –> 退出条件:1.工资总额>5w 2.%notfound
变量:1.初始值 2.如何得到
涨工资的人数:
countEmp number := 0;
涨后的工资总额:
salTotal number;
1. select sum(sal) into salTotal from emp;
2.涨后的工资总额= 涨前的工资总额+ sal* 0.1
*/
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
fetch cemp into pempno, psal;
exit when cemp%notfound;
--涨后的工资总额(使用涨后的工资判断是否大于50000)
exit when salTotal + psal*0.1 >50000;
salTotal := salTotal + psal*0.1;
update emp set sal = sal*1.1 where empno = pempno;
countEmp := countEmp + 1;
end loop;
--关闭光标
close cemp;
commit;
dbms_output.put_line('涨工资的人数为:'||countEmp||',涨后的工资总额为:'||salTotal);
end;
实例三.–用PL/SQL语言编写一程序,实现按部门分段
–(6000以上、6000-3000,3000元以下)统计各个
–工资段的职工人数、以及各部门的工资总额(工资总额中不包括奖金)
--创建结果表--存储结果数据
create table msg
(deptno number,
count1 number,
count2 number,
count3 number,
saltotal number);
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;
begin
--打开部门的光标
open cdept;
loop
--取出一个部门
fetch cdept into pdeptno;
exit when cdept%notfound;
--初始化的工作
count1:=0;count2:=0;count3:=0;
--得到部门的工资总额
--1、select sum(sal) into saltotal from emp where deptno=???
select sum(sal)into saltotal from emp where deptno=pdeptno;
--取部门中员工的薪水光标
open cemp(pdeptno);
loop
fetch cemp into sal;
end loop;
close cemp;
--保存当前部门的结果
insert into msg values(pdeptno,count1,count2,count3,nvl(saltotal,0));
end loop;
--关闭部门的光标
close cdept;
--提交
commit;
dmbs_output.put_line("统计完成");
end;