PL/SQL基础

PL/SQL基础

–打开输出开关
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语言具有过程处理能力

  1. PL/SQL是对SQL语言的扩展
  2. PL/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);

IF语句

  1. IF 条件 THEN 语句1;
    语句2;
    END IF;
  2. IF 条件 THEN 语句1;
    ELSE 语句2;
    END IF;
  3. IF 条件 THEN 语句;
    ELSEIF 语句 THEN 语句;
    ELSE 语句;
    END IF;

/*
判断用户从键盘输入的数字
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;
/

#例外
例外是程序设计语言提供的一种功能,用来增强程序的健壮性和容错性。

  1. 系统例外

  2. 自己定义例外

    系统例外之no_data_found

    –系统例外: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

    –系统例外: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;
    /

系统例外之zero_divide

–系统例外:被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

--系统例外: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
/

PLSQl程序的设计

瀑布模型

--案例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;
/

你可能感兴趣的:(ORACLE学习)