–打开输出开关
set serveroutput on
–打印 Hello World
declare
–说明部分(变量、光标或者例外),如果没有可以不写
begin
–程序体
dbms_output.put_line(‘Hello World’);
end;
/
–查看程序包的结构
desc dbms_output
PL/SQL程序
PL/SQL(Procedure Language/SQL)
PL/SQL是Oracle对sql语言的过程化扩展
–指在SQL命令语言中增加了过程处理语句(如分支、循环等)
–使得SQL语言具有过程处理能力
PL/SQL:简单、搞笑、灵活、实用
PL/SQL的程序结构
declare
说明部分(变量说明、光标申明、例外说明)
begin
语句序列(DML)语句语句
exception
例外处理语句
end;
/
定义基本变量
类型:char varchar2 date number boolean long
举例:
var1 char(15);
married boolean := true;
psal number(7,2);
–使用基本变量类型
declare
–定义基本变量类型
–基本数据类型
pnumber number(7,2);
–字符串变量
pname varchar2(20);
–日期变量
pdate date;
begin
pnumber := 1;
dbms_output.put_line(pnumber);
pname:= ‘Tom’;
dbms_output.put_line(pname);
pdate:= sysdate;
dbms_output.put_line(pdate);
–计算明天的日期
dbms_output.put_line(pdate+1);
end;
/
引用型变量
举例:
emp_rec emp.enmae%type;
*记录型变量分量的引用(理解成数组)
emp_rec.ename := ‘ADAMS’;
例:
–引用型变量
set serveroutput on
declare
–定义引用型变量:查询并打印7839的姓名和薪水
–pename varchar2(20);
–psal number;
pename emp.ename%tyep;
psal enp.sal%type;
begin
–得到7839的姓名和薪水
select ename,sal into pname,psal from emp where empno = 7839;
–打印姓名和薪水
dbms_output.put_line(pname||’的薪水是:’psal);
end;
/
–使用记录型变量,查询并打印7839的姓名和薪水
set serveroutputon
declare
–定义记录型变量:注意代表一行
emp_rec emp%rowtype;
begin
–得到7839一行的信息
select * into emp from emp where empno = 7839
–打印姓名和薪水
dbms_output.put_line(emp_rec.ename||’薪水是 ‘emp_rec.sal);
/*
判断用户从键盘输入的数字
1.如何使用if语句
2.接收一个键盘输入(字符串)
*/
set serveroutput on
–接收一个键盘输入
–num: 地址值,含义是:在该地址上保存了输入的值
accept num prompt ‘请输入一个数字:’
declare
–定义变量保存用户从键盘输入的数字
pnum number := #
begin
–执行if语句进行条件判断
if pnum = 0 THEN dbms_output.put_line(“您输入的是0”);
elseif pnum = 1 then dbms_output.put_line(“您输入的是1”);
else dbms_output.put_line(“其他数字”);
end if;
end;
/
WHILE total <= 25000 LOOP
….
total := total + salary;
END LOOP;
–使用while循环打印数字的1-10
set serveroutput on
declare
–定义循环变量
pnum number := -1;
begin
while pnum <= 10 LOOP
dbms_output.put_line(num);
--使变量+1
num := num + 1;
end loop;
end;
/
Loop
EXIT [when 条件];
….
end loop;
–使用Loop循环打印1-10
set serveroutput on
declare serveroutput on
declare
–定义循环变量
pnum number := 1;
begin
loop
–退出条件:循环变量大于10
exit when pnum > 10;
–打印改变量的值
dbms_output.put_line(pnum);
–循环变量+1
pnum := pnum + 1;
end loop ;
end;
/
FOR I IN 1..3 LOOP
语句序列;
END LOOP;
–使用for 循环打印1-10’
set serveroutput on
declare
–定义循环变量
pnum number := 1
begin for pnum in 1..10 LOOP
end loop;
end;
/
就是一个结果集(result set)
CURSOR 光标名 [(参数名 数据类型[,参数名 数据类型]…)]
IS SELECT 语句;
cursor c1 is select ename from emp;
– 打开光标
open c1;
– 关闭光标
close c1;(关闭游标释放资源)
fetch c1 into pename;(取一行到变量中)
光标的具体案例-1
/*
1.光标的属性
%found %notfound
*/
–使用光标查询员工姓名和工资,并打印
set serveroutput on
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;
–司考:1.循环什么时候能够退出
–2fetch不一定能够取到记录
–exit when 没有取到记录
exit when cemp%notfound
–打印
dbms_output.put_line(pename||”的薪水是”||psal);
end loop;
–关闭光标
close cemp;
end;
/
–光标的案例2:给员工涨工资,总裁1000,经理800,其他400
set serveroutput on
declare
–定义光标代表给哪些员工涨工资
–alter table “SOCTT”.”ENP” rename column “JOB” to empjob
cursor cemp is select empno,empjob from emp;
pempno emp.empno%type;
pjob emp.job%type;
begin
–打开光标
open cemp;
loop
–取出一个员工
fetch cemp into pempno,pjob;
exit when cemp%nofound;
–判断员工的职位
if pjob = “PRESIDENT” then update emp set sal=sal+100 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;
–对于oracle,默认的事务隔离级别是 read commiteed
–事务的ACID
commit;
dbms_output.put_line(“涨工资完成”);
end;
/
%found %notfound
%isopen:判断光标是否打开
%rowcount:影响的行数
默认情况下,oracle数据库中只允许在同一个会话中,代开300个光标;
show paramater cursor
修改光标数的限制:
alter system set open_cursors = 400 scope = both;
scope取值有3个 both memory spfile(数据库需要重启)
set serveroutput on
declare
cursor cemp is select empno,empjob from emp;
pempno emp.empno%type;
pjob emp.empjob%type;
begin
–打开光标
open cemp;
if cemp % isopen then
dbms_output.put_line(“光标已经打开”);
else
dbms_output.put_line(“光标没有打开”);
end if;
loop
–取出一条记录
fetch cemp into pempno,pjob;
exit when cem%notfound;
–打印rowcount的值
dbms_output.put_line('rowcount'||cemp%rowcount);
end loop;
–关闭光标
close cemp;
end;
/
CURSOR 光标名 [(参数名 数据类型[,参数名 数据类型]…)]
IS SELECT 语句;
–查询某个部门中员工的姓名
set serveroutput on;
declare
–定义带参数的光标
cursor cemp(dno number) is select ename from emp where deptno = dno;
pename emp.ename%type;
begin
–代开光标
open cemp(10);
loop
–取出每个员工的姓名
fetch cemp into pename;
exit whern cemp%notfound;
end loop;
--关闭光标
close cemp;
end;
/
#例外
例外是程序设计语言提供的一种功能,用来增强程序的健壮性和容错性。
系统例外
自己定义例外
–系统例外:no_data_found
set serveroutput on
declare
pename emp.ename%type;
begin
–查询员工是1234的员工姓名
select ename into pename from emp where empno = 1234;
exception
when no_data_found then dbms_output.put_line(“没有找到该员工”);
when others then
dbms_output.put_line(“其他例外”);
end;
/
–系统例外:too_many_rows
set serveroutput on
declare
–定义变量
pename emp.ename%type;
begin
–查询所有10号部门的员工姓名
select ename into pename from emp where deptno = 10;
exception
when too_many_rows then dbms_output.put_line(“select into 匹配多了”);
when others then dbms_output.put_line(“其他例外”);
end;
/
–系统例外:被0除 zero_divide
set serveroutput on;
declare
--定义一个基本变量
pnum number;
begin
pnum:=1/0;
exception
when zero_divide then dbms_output.put_line("0不能做除数");
when others dbms_output.put_line("其他例外");
end;
/
--系统例外:value_error
ser serveroutput on
declare
--定义一个number类型的变量
pnum number;
begin
pnum = 'abc';
exception
when value_error then dbms_output.put_line("算数或者转换错误");
when others then dbms_output.put_line("其他例外");
end;
/
定义变量,类型是exception
使用raise抛出自定义例外
declare
--自定义变量
My_job char(10);
v_sal emp.sal%type;
--定义一个例外
No_data exception;
--定义一个光标
cursor c1 is select distinct job from emp order by job;
begin
--打开光标
open c1;
fetch c1 into v_job;
if c1%notfound then raise no_data;
end if;
--关闭光标
close c1;
exception
when no_date then insert into emp values('fetch 语句没有获得数据或数据已经处理完毕');
end
/
--案例1:统计每年入职的员工人数
/*
select to_char(hiredate,'yyyy') from emp;
光标->循环->退出条件:notfound
每年入职的员工人数:
count80 number := 0;
count81 number := 0;
count82 number := 0;
count87 number := 0;
*/
ser serveroutput on;
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;
--输出结果
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);
--关闭光标
close cemp;
end;
/