简介
存储过程是一系列sql语句的集合,可以封装复杂的逻辑,实现特定的功能,可以提高执行速度和代码的复用性,预先编译后存储在数据库中,可以通过指定存储过程的名称对其进行调用。
本文主要讲解oracle存储过程语法,包括:总体结构、存储过程声明、参数定义、变量声明、游标声明、行数据类型声明、变量赋值、条件判断、while循环、for循环、游标使用、异常捕捉、异常处理、存储过程调用、存储过程代码示例、调用代码示例、调用结果展示。
总体结构
一个完整的存储过程结构主要包括:过程声明部分、过程执行部分、异常处理部分,如下所示。
create or replace procedure 存储过程名称(参数定义部分)
as或is
变量声明部分
begin
过程执行部分
exception
异常处理部分
end;
样例准备
先准备样例表testtable01,数据如下图,后续所有代码示例查询的数据都来自这个表。
过程声明部分
声明格式
create or replace procedure 存储过程名称(参数定义部分)
as或is
其中,【or replace】表示如果已存在同名的存储过程,则直接替换,即将其覆盖掉,这部分也可以省略,省略后,执行编译时,如果发现同名的存储过程,则会报错提示ora-00955,如下图。as或is两种写法效果相同,任选其一。
参数定义
格式:【参数名 输入输出类型 数据类型】,可定义输入或输出的参数,可以不带参数,也可以定义一个或多个参数,多个参数用英文逗号隔开,如下所示。
过程声明和参数定义示例
create or replace procedure testsp01( para01 in varchar2, para02 in int, para03 out varchar2 ) as
para01、para02、para03为自定义的参数名;in或out表示输入或输出参数,输入参数是在调用存储过程时传入的,输出参数是在存储过程内部赋值的,可以输出;varchar2、int表示参数的数据类型。
说明:【in out】表示该参数既是输入参数也是输出参数。
变量声明
格式:【变量名 数据类型】,变量声明是在begin前面。
可以定义存储过程中需要用到的变量,每个变量用英文分号结尾,如下所示。
var01 varchar2(10); var02 varchar2(20); var03 int; var04 number(5); var05 varchar2(50);
游标声明
格式:【cursor 游标名称 is 查询语句】,游标是内存中用于存储和检索查询结果集的一种数据结构,可以用来遍历的有多条数据的查询结果。
示例:
cursor cursor01 is select col01,col02,col03 from testtable01 where col02 is not null;
行数据类型
声明游标之后,需要再声明一个行数据类型,用以存储游标中的某一行数据,也可以存储表中的一行数据。
格式:
行变量名称 游标名称%rowtype;
行变量名称 表名称%rowtype;
示例:
row01 cursor01%rowtype; row02 testtable01%rowtype;
过程执行部分
变量赋值
格式:【变量名:=变量值】,如下所示,可以将常量、变量等赋值给变量。
var01:='hello'; var02:=var01; var03:=8; var04:=1.8; var05:=var02||' world';
也可以在变量声明的时候直接赋值,如下所示。
var03 int:=8; var04 number(5,2):=1.8; var05 varchar2(50):='hello world';
还可以把sql语句的查询结果赋值给变量,格式:【select 字段名或表达式 into 变量名 from ...】,如下所示。
select count(1) into var03 from testtable01; select col02 into var01 from testtable01 where col01='id01'; select replace(col02,'value','hello')||' world' into var05 from testtable01 where col01='id01';
条件判断
格式如下:若条件判断表达式01为真,则执行代码块01,当不满足表达式01时,继续判断,若条件判断表达式02为真,则执行代码块02,若前面的条件都不满足,则执行代码块03。其中elsif(注意写法不是elseif)和else部分都可以省略。
if 条件判断表达式01 then
代码块01
elsif 条件判断表达式02 then
代码块02
else
代码块03
end if;
示例:
if var01 like 'value%' then var02:='ret01'; elsif var03>1 then var02:='ret02'; else var02:='ret03'; end if;
while循环
第一种写法如下:如果条件表达式为真,再执行里面的代码块,否则不执行。
while 条件表达式 loop
代码块
end loop ;
第二种写法如下:先执行一次loop中的代码块,再判断条件表达式,如果为真,则退出循环,否则,继续执行循环,这种写法与第一种写法的区别在于,不论条件表达式结果如何,loop中的代码块会至少执行一次。
loop
代码块
exit when 条件表达式
end loop;
for循环
格式:每一次执行循环时,会将索引自增一次,从索引范围的最小值开始自增,伴随着每一次循环,直到索引达到索引范围的最大值,就退出循环。
for 索引 in 索引范围 loop
代码块;
end loop;
示例:
-- for循环依次输出1到8 for i in 1..8 loop var08:=var08||i; end loop; dbms_output.put_line('for循环输出1到8:'||var08);
游标使用
打开游标:【open 游标名称】;
获取游标数据放入行变量:【fetch 游标名称 into 行变量名称】,其中,fetch在获取当前行数据的同时,还会把游标指针推进到下一条纪录,一般放在循环结构中遍历获取每一条数据。
游标的属性:
【游标名称%isopen】:表示游标是否打开,正常情况返回布尔型;
【游标名称%found】:表示游标是否获取到数据,正常情况返回布尔型;
【游标名称%notfound】:表示游标是否没有获取到数据,正常情况返回布尔型;
【游标名称%rowcount】:返回游标已经遍历获取的记录数,不是总数量,返回int型。
示例:
var061:=cursor01%isopen; -- 游标cursor01是否打开 var062:=cursor01%found; -- 游标cursor01是否获取到数据 var063:=cursor01%notfound; -- 游标cursor01是否没有获取到数据 var064:=cursor01%rowcount; -- 返回游标cursor01已经遍历获取的记录数,不是总数量
关闭游标:【close 游标名称】。
示例1,使用while...loop循环方式读取游标数据:
-- while...loop循环方式 dbms_output.put_line('while...loop循环方式:'); open cursor01; -- 打开游标cursor01 var061:=cursor01%isopen; -- 游标是否打开 var062:=cursor01%found; -- 游标是否获取到数据 var063:=cursor01%notfound; -- 游标是否没有获取到数据 fetch cursor01 into row01; -- 从游标cursor01获取行数据赋给行变量row01,并将游标推进到下一行。 while cursor01%found loop --如果cursor01%found结果为真,则执行while循环 begin var_col01 := row01.col01; -- 获取行变量中的具体字段值赋给左边的变量 var_col02 := row01.col02; -- 获取行变量中的具体字段值赋给左边的变量 dbms_output.put_line('获取记录数:'||cursor01%rowcount); -- 输出内容 dbms_output.put_line('当前行数据:'||var_col01||','||var_col02); -- 输出内容 fetch cursor01 into row01; -- 从游标cursor01获取行数据赋给行变量row01,并将游标推进到下一行。 end; end loop; close cursor01; -- 关闭游标cursor01
示例2,使用loop... exit when...循环方式读取游标数据:
-- loop... exit when...循环方式 dbms_output.put_line('loop... exit when...循环方式:'); open cursor01; -- 打开游标cursor01 loop fetch cursor01 into row01; -- 从游标cursor01获取行数据赋给行变量row01,并将游标推进到下一行。 exit when cursor01%notfound; -- 如果cursor01%notfound结果为真,则退出循环。 var_col01 := row01.col01; -- 获取行变量中的具体字段值赋给左边的变量 var_col02 := row01.col02; -- 获取行变量中的具体字段值赋给左边的变量 dbms_output.put_line('获取记录数:'||cursor01%rowcount); -- 输出内容 dbms_output.put_line('当前行数据:'||var_col01||','||var_col02); -- 输出内容 end loop ; close cursor01; -- 关闭游标cursor01
示例3,使用for循环方式读取游标数据:
-- for循环读取游标数据 dbms_output.put_line('for循环读取游标数据:'); for row01 in cursor01 loop -- 遍历游标cursor01获取数据赋给行变量row01 var_col01 := row01.col01; -- 获取行变量中的具体字段值赋给左边的变量 var_col02 := row01.col02; -- 获取行变量中的具体字段值赋给左边的变量 dbms_output.put_line('获取记录数:'||cursor01%rowcount); -- 输出内容 dbms_output.put_line('当前行数据:'||var_col01||','||var_col02); -- 输出内容 end loop;
异常处理部分
异常捕捉
格式:exception可以捕捉到存储过程执行中遇到的异常,when后面是具体的异常名称,捕捉到具体异常后,就会执行对应when下面的异常处理代码块,如果捕捉到的异常和前面任何一个when后面的异常名称都不匹配,则直接执行【when others then】下面的异常处理代码。
exception
when 异常01 then
异常处理代码块01
when 异常02 then异常处理代码块02
......
when others then
异常处理代码块n
异常处理部分也可以只有others部分,格式如下,捕捉到任何异常都会跳转到others对应的异常处理代码块。
exception
when others then
异常处理代码块
异常处理
sqlcode:获取错误代码,
sqlerrm:获取具体的错误信息,
rollback:回滚事务。
异常处理示例:
exception when no_data_found then dbms_output.put_line('未查询到数据!'); when cursor_already_open then dbms_output.put_line('游标已经打开!'); when others then dbms_output.put_line(sqlcode); -- 输出错误代码 dbms_output.put_line(sqlerrm); -- 输出错误信息
调用存储过程 调用命令格式
如果存储过程不带参数,调用格式如下。
call 存储过程名称();
如果存储过程只带输入参数,参数值用英文逗号隔开,传入的值要和存储过程定义的参数的顺序和类型保持一致,调用格式如下。
call 存储过程名称(参数值1,参数值2,...);
如果存储过程带输出参数,比如某个存储过程有三个参数,前两个为输入参数,第三个为输出参数,调用格式如下,需要先定义一个变量用来接收输出参数值,数据类型要和输出参数相同。
begin
declare
变量名01 数据类型;
begin
存储过程名称(传入值01,传入值02,变量名01);
end;
end;
完整存储过程示例
-- 存储过程声明,可以带参数,也可以不带参数 create or replace procedure testsp01( para01 in varchar2, para02 in int, para03 out varchar2 ) as -- 变量定义,可以在变量定义时赋值。 var01 varchar2(10); var02 varchar2(20); var03 int:=0; var04 number(5,2):=8.88; var05 varchar2(50):='initvalue'; var06 int; var061 boolean; var062 boolean; var063 boolean; var07 varchar2(30); var08 varchar2(20):=''; var_col01 varchar2(20); var_col02 varchar2(20); -- 游标声明 cursor cursor01 is select col01,col02,col03 from testtable01 where col02 is not null; -- 行变量声明 row01 cursor01%rowtype; row02 testtable01%rowtype; begin -- 过程执行部分 -- 变量赋值,可以将常量或变量赋值给变量 dbms_output.put_line('变量赋值示例:'); var01:='hello'; var02:=var01; var03:=8; var04:=1.8; dbms_output.put_line('var01:'||var01||','||'var02:'||var02||','||'var03:'||var03||','||'var04:'||var04); -- 通过sql查询给变量赋值 select col02 into var05 from testtable01 where col01='id01'; select count(1) into var06 from testtable01; select replace(col02,'value','hello')||' world' into var07 from testtable01 where col01='id01'; dbms_output.put_line('var05:'||var05||','||'var06:'||var06||','||'var07:'||var07); -- if判断示例 dbms_output.put_line('if判断示例:'); if para01 like 'value%' then dbms_output.put_line('if判断满足第一个分支'); elsif para02>1 then dbms_output.put_line('if判断满足第二个分支'); else dbms_output.put_line('if判断满足第三个分支'); end if; -- while...loop循环方式读取游标数据 dbms_output.put_line('while...loop循环方式读取游标数据:'); open cursor01; -- 打开游标cursor01 var061:=cursor01%isopen; -- 游标cursor01是否打开 var062:=cursor01%found; -- 游标cursor01是否获取到数据 var063:=cursor01%notfound; -- 游标cursor01是否没有获取到数据 fetch cursor01 into row01; -- 从游标cursor01获取行数据赋给行变量row01,并将游标推进到下一行。 while cursor01%found loop --如果cursor01%found结果为真,则执行while循环 begin var_col01 := row01.col01; -- 获取行变量中的具体字段值赋给左边的变量 var_col02 := row01.col02; -- 获取行变量中的具体字段值赋给左边的变量 dbms_output.put_line('获取记录数:'||cursor01%rowcount); -- 输出内容 dbms_output.put_line('当前行数据:'||var_col01||','||var_col02); -- 输出内容 fetch cursor01 into row01; -- 从游标cursor01获取行数据赋给行变量row01,并将游标推进到下一行。 end; end loop; close cursor01; -- 关闭游标cursor01 -- loop... exit when...循环方式读取游标数据 dbms_output.put_line('loop... exit when...循环方式读取游标数据:'); open cursor01; -- 打开游标cursor01 loop fetch cursor01 into row01; -- 从游标cursor01获取行数据赋给行变量row01,并将游标推进到下一行。 exit when cursor01%notfound; -- 如果cursor01%notfound结果为真,则退出循环。 var_col01 := row01.col01; -- 获取行变量中的具体字段值赋给左边的变量 var_col02 := row01.col02; -- 获取行变量中的具体字段值赋给左边的变量 dbms_output.put_line('获取记录数:'||cursor01%rowcount); -- 输出内容 dbms_output.put_line('当前行数据:'||var_col01||','||var_col02); -- 输出内容 end loop ; close cursor01; -- 关闭游标cursor01 -- for循环依次输出1到8 for i in 1..8 loop var08:=var08||i; end loop; dbms_output.put_line('for循环输出1到8:'||var08); -- for循环读取游标数据 dbms_output.put_line('for循环读取游标数据:'); for row01 in cursor01 loop -- 遍历游标cursor01获取数据赋给行变量row01 var_col01 := row01.col01; -- 获取行变量中的具体字段值赋给左边的变量 var_col02 := row01.col02; -- 获取行变量中的具体字段值赋给左边的变量 dbms_output.put_line('获取记录数:'||cursor01%rowcount); -- 输出内容 dbms_output.put_line('当前行数据:'||var_col01||','||var_col02); -- 输出内容 end loop; --给输出参数赋值 para03:='存储过程执行成功!'; exception -- 异常处理部分 when no_data_found then dbms_output.put_line('未查询到数据!'); when cursor_already_open then dbms_output.put_line('游标已经打开!'); when others then dbms_output.put_line(sqlcode); -- 输出错误代码 dbms_output.put_line(sqlerrm); -- 输出错误信息 end;
调用存储过程示例
begin declare -- 定义变量接收输出参数值,数据类型要和输出参数相同 outpara varchar2(50); begin -- 调用存储过程,给输入参数赋值,将事先定义的变量传给输出参数。 testsp01('value_in',8,outpara); -- 打印输出参数 dbms_output.put_line('输出参数值:'||outpara); end; end;
调用输出结果展示
到此这篇关于oracle存储过程语法详解的文章就介绍到这了,更多相关oracle存储过程语法内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论