您的位置:首页 > 数据库 > Oracle

Oracle PL/SQL 基础语法、游标、例外

2018-02-24 21:56 561 查看

一、基础语法

PL/SQL 是Oracle对SQL语言的扩展,可以对SQL进行编程。

基本框架

set serveroutput on;
-- 在SQL Developer中显示输出

-- 基本框架
declare -- 必需
-- 声明变量、常量、游标、例外
begin   -- 必需

-- do something

exception  -- 非必需
-- 例外
end;    -- 必需


变量

PL/SQL 的变量分为普通变量、引用型变量、记录型变量。

变量声明格式:变量名 变量类型 变量值。

变量的类型为Oracle的数据类型,如number、varchar2等。

set serveroutput on;

declare
-- 声明普通变量并赋值
s1 number := 3; -- 赋值使用 :=

-- 声明引用型变量
s2 emp.ename%type;  -- 引用emp表的ename类的类型

-- 声明记录型变量
s3 emp%rowtype;     -- emp表中一条记录数据的集合
begin

-- 输出s1
DBMS_OUTPUT.PUT_LINE(s1);

-- 给s2赋值
select ename into s2 from emp where empno=7788;
-- into s2,将编号为7788员工的名字赋值给s2
-- 输出s2
DBMS_OUTPUT.PUT_LINE(s2);

-- 给s3赋值
select * into s3 from emp where empno=7788;
-- 使用s3 格式:s3.字段名
DBMS_OUTPUT.PUT_LINE(s3.ename || '--' || s3.job);
-- || 表示连接符
end;


常量

常量的声明使用constant关键字。

set serveroutput on;

declare
-- 声明常量并赋值
s1 constant number :=55;
begin
-- 输出
DBMS_OUTPUT.PUT_LINE(s1);
end;


条件语句

条件语句有if、if…else、多重if。

if语句语法:

if 条件 then

….

end if;

if…else语法:

if 条件 then



else



end if;

多重if语法:

if 条件 then



elsif 条件 then



else



end if;

注意是elsif,而不是else if。

基本用法

set serveroutput on;

declare
-- 声明一个变量
s1 number :=55;
begin
-- 使用if 进行判断
if s1 = 55 then -- 比较使用的是=,不是java 的 ==
DBMS_OUTPUT.PUT_LINE(s1);
end if;

-- 使用if else 进行判断
if s1>20 then
dbms_output.put_line(s1 || '大于 20');
else
DBMS_OUTPUT.PUT_LINE(s1 || '小于 20');
end if;

-- 使用多重if 进行判断
if s1>100 then
DBMS_OUTPUT.PUT_LINE('大于100');
elsif s1>80 then    -- elsif then 可以写多个
DBMS_OUTPUT.PUT_LINE('大于80');
elsif s1>60 then
DBMS_OUTPUT.PUT_LINE('大于60');
else
DBMS_OUTPUT.PUT_LINE('小于60');
end if;

end;


循环语句

循环语句有while、do…while、for语句。

while语法

while 条件

loop



end loop;

do…while语法

loop



exit when 条件;

end loop;

for语法

for 当前循环的值 in 起始..终止

loop



end loop;

注意:起始和终止之间是两个点,不是三个。

基本用法

set serveroutput on;

declare
-- 定义变量
num number := 1;
sumNum number := 0;
begin
-- 使用while 循环输出1-5
while num<=5
loop
dbms_output.put_line(num);
num := num + 1; -- 将num加1,不要写成=号
end loop;
DBMS_OUTPUT.put_line('----------------');

-- 使用do...while 计算1-5的和
num := 1;
loop
sumNum := sumNum + num;
num := num + 1;
exit when num>5;
end loop;
dbms_output.put_line(sumNum);
DBMS_OUTPUT.put_line('----------------');

-- 使用for循环 输出1-5
for var in 1..5 -- 注意写法
loop
DBMS_OUTPUT.PUT(var || '--');
-- 这里是put,如果只使用put的话,不会输出,要结合put_line一起使用
end loop;
DBMS_OUTPUT.put_line('');
end;


二、游标

用于存储查询到的数据,和记录型变量不同,记录型变量只能存储一行记录,但是游标可以存储多行记录。

语法

cursor 游标名 (参数列表)

is select ….

使用步骤

打开游标:open 游标名 (参数);

取值:fetch 游标名 into 取到的值放到哪里;

关闭游标:close 游标名;

属性

有四个常用的属性:

%isopen:判断游标是否打开。

%rowocount:取得的记录数。

%found:为true表示发现下一个数据。反之。

%notfound:和found相反。

基本用法

set serveroutput on;

declare
-- 定义游标 获取emp表中的所有员工的名字
cursor names is
select ename from emp;
-- 定义引用变量 用于存放fetch每次取到的值
ename emp.ename%type;
begin
open names; -- 打开游标

if names%isopen then
dbms_output.put_line('1');
else
dbms_output.put_line('2');
end if;

-- 获取所有名字,使用循环
loop
fetch names into ename;
exit when names%notfound;
dbms_output.put_line(ename || ' -- '|| names%rowcount);
end loop;
close names; -- 关闭游标
end;


对于动态的查询数据,就要使用游标的参数。看下面的例子:

set serveroutput on;
/* 获取每个部门工资高于2000的人数
要获取每个部门编号进行查询。
*/
declare
-- 定义游标 获取dept表中的部门编号
cursor deptnos is
select deptno from dept;
-- 定义引用变量 用于部分编号的值
deptno dept.deptno%type;

-- 定义游标 获取不同部门编号的工资高于2000的人数
cursor sals(deptno1 number) is  -- 参数表示部门编号
select sal from emp where deptno=deptno1;
-- 在测试的时候,因为参数名字和where字段名相同,导致错误,找了好一会才发现。对于这种where比较的
-- 条件,最好不要字段名和参数名相同
-- 根据参数来查询
-- 定义引用变量 存放每次取到的工资
sal emp.sal%type;
-- 定义普通变量 用于获取满足要求的人数
pnum number := 0;
begin
open deptnos; -- 打开游标

-- 遍历部门编号游标
loop
deptno := 0;
fetch deptnos into deptno;
exit when deptnos%notfound;

-- 根据部门编号获取工资>2000 的人数
pnum := 0;
open sals(deptno);
loop
fetch sals into sal;
exit when sals%notfound;
if sal > 2000 then
pnum := pnum + 1;
end if;
end loop;
close sals;
DBMS_OUTPUT.PUT_LINE(deptno || ' 部门编号工资大于2000有 ' || pnum || ' 人');
end loop;
close deptnos; -- 关闭游标
end;


三、例外

和java中的异常类似,分为系统例外和自定义列外。

常见系统例外

cursor_already_open :游标已经开启了,再次开启出现的异常

no_data_found:没有找到数据

too_many_rows:select…into 时匹配多个行

zero_divide:被0除

value_error:算数或类型转换错误

timeout_on_resource:等待资源超时

storage_error:运行PL/SQL时,超出内存空间

例外语法

declare

begin

exception

when 例外1 then …;

when 例外2 then …;



when others then …;

end;

set serveroutput on;
declare
-- 定义变量
snum number;
begin

snum := 1/0;

exception
when zero_divide then dbms_output.put_line('被零除');
when others then dbms_output.put_line('其他例外');
end;


自定义例外语法

declare

例外名 exception;

begin

if 条件 then

raise 列外名; 抛出例外

end if;

exception

when 例外1 then …;

when 例外2 then …;



when others then …;

end;

set serveroutput on;
declare
-- 定义例外
smallDate exception;

abc number := 2;
begin

if abc < 10 then
raise smallDate; -- 抛出例外
end if;

exception
when zero_divide then dbms_output.put_line('被零除');
-- 捕获例外
when smallDate then dbms_output.put_line('数据过小');
when others then dbms_output.put_line('其他例外');
end;


浏览存储过程、存储函数、触发器知识,可以查看:http://blog.csdn.net/q_sea__/article/details/79362804
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: