1、创建存储过程规范
CREATE OR REPLACE PROCEDURE 存储过程名字(参数1 IN varchar,参数2 OUT NUMBER) IS
–定义变量
V_LOG ETL_PROCLOG%ROWTYPE; 取与表ETL_PROCLOG的字段作为变量V_LOG的属性,赋值时或取值时 打点.取值或赋值
变量1 INTEGER :=0; :=初始化变量
变量2 DATE;
BEGIN
dbms_output.put_line(‘开始执行存储过程’);
–执行体
SELECT col1,col2 into 变量1,变量2 FROM typestruct where xxx;
EXCEPTION
dbms_output.put_line(‘存储过程错误处理’);
END 存储过程名字;
2、创建日志表
新建一张表(PROC_LOG)用于存储存储过程的执行情况信息:
create table PROC_LOG{
procDate varchar2(10), --存储过程执行日期
procName varchar2(100), --存储过程名称
stepNumber varchar2(10), --存储过程执行的步数
numRow number(20), --存储过程每一步影响的行数
dealStartTime varchar2(10), --存储过程每一步执行的开始时间
dealEndTime varchar2(10), --存储过程每一步执行的结束时间
dealFlg varchar2(4), --存储过程每一步执行的结果 0-成功,-1-失败
errNo number(20), --错误编码
errMsg varchar2(200), --错误信息
errLevel varchar2(10) --错误级别
}
3、存储过程范例
INOUT 输入 PUTOUT 输出 存储过程执行的结果
CREATE OR REPLACE PROCEDURE PROC_EXAMPLE(input IN VARCHAR2,output OUT VARCHAR2) IS
--存储过程示例
V_LOG PROC_LOG%ROWTYOE;
V_AQLCOUNT NUMBER; --存储过程影响的数据条数
E_DATE VARCHAR2(10); 存储过程执行的日期
/**
调用:
DECLARE
input varchar(10);
BEGIN
input :='0';
PROC_EXAMPLE(input);
END;
日志查询:select * from PROC_LOG where procName='PROC_EXAMPLE'
Deac:存储过程示例
Author:zhaoqiyin
Tester:zhaoqiyin
Output param:output ----执行状态 0-成功,-1-失败
*/
------------------------------------------------------------------------------------------------------------------
BEGIN
--初始化一些变量
V_LOG.procDate :=TO_CHAR(SYSDATE,'YYYY-MM-DD');
V_LOG.procName :='PROC_EXAMPLE'
putout :='0';
dbms_output.put_line('开始执行存储过程-PROC_EXAMPLE');
------------------------------------------------------------------------------------------------------------------
--步骤1
V_LOG.stepNumber :='1'; --存储过程步骤
V_LOG.dealStartTime :=TO_CHAR(SYSDATE,'YYYY-MM-DD HH24:MI:SS');
dbms_output.put_line('存储过程第1步清空某一张表 开始');
execute immediate 'truncate table user_info'; --执行ddl语句 需要放在execute immediate 'ddl语句';
V_LOG.dealEndTime :=TO_CHAR(SYSDATE,'YYYY-MM-DD HH24:MI:SS');
V_AQLCOUNT :='1'; --sql影响的行数 如果是ddl语句 取不到值默认为1
dbms_output.put_line('存储过程第1步清空某一张表结束,共计清理数据【'||V_AQLCOUNT||'】行');
--记录日志
insert into PROC_LOG values(V_LOG.procDate,V_LOG.procName,V_LOG.stepNumber,V_AQLCOUNT,V_LOG.dealStartTime,V_LOG.dealEndTime,putout,null,null,null);
------------------------------------------------------------------------------------------------------------------
--步骤2-1
V_LOG.stepNumber :='2-1'; --存储过程步骤
V_LOG.dealStartTime :=TO_CHAR(SYSDATE,'YYYY-MM-DD HH24:MI:SS');
dbms_output.put_line('存储过程第2-1步 插入操作 开始');
insert into user_info select * from user_info_old;
V_LOG.dealEndTime :=TO_CHAR(SYSDATE,'YYYY-MM-DD HH24:MI:SS');
V_AQLCOUNT :=SQL%ROWCOUNT; --sql影响的行数 如果是ddl语句 取不到值默认为1
dbms_output.put_line('存储过程第2-1步 插入操作结束,共计清理数据【'||V_AQLCOUNT||'】行');
--记录日志
insert into PROC_LOG values(V_LOG.procDate,V_LOG.procName,V_LOG.stepNumber,V_AQLCOUNT,V_LOG.dealStartTime,V_LOG.dealEndTime,putout,null,null,null);
commit;
------------------------------------------------------------------------------------------------------------------
--错误抓取
EXCEPTION
WHEN OTHERS THEN
putout :='-1';
V_LOG.errNo :=SQLCODE;
V_LOG.errMsg :=substr(SQLERRM,1,200);
V_LOG.errLevel :='2';
dbms_output.put_line('存储过程第【'||V_LOG.stepNumber||'】步执行错误,错误编码【'||V_LOG.errNo||'】,错误内容【'||V_LOG.errMsg||'】');
ROLEBACK;
------------------------------------------------------------------------------------------------------------------
insert into PROC_LOG values(V_LOG.procDate,V_LOG.procName,V_LOG.stepNumber,V_AQLCOUNT,V_LOG.dealStartTime,V_LOG.dealEndTime,putout,V_LOG.errNo,V_LOG.errMsg,V_LOG.errLevel);
commit;
------------------------------------------------------------------------------------------------------------------
END;
关于oracle存储过程的若干问题备忘
1.在oracle中,数据表别名不能加as,如:
select a.appname from appinfo a;-- 正确
select a.appname from appinfo as a;-- 错误
2.在存储过程中,select某一字段时,后面必须紧跟into,如果select整个记录,利用游标的话就另当别论了。
select af.keynode into kn from APPFOUNDATION af
where af.appid=aid and af.foundationid=fid;-- 有into,正确编译
select af.keynode from APPFOUNDATION af
where af.appid=aid and af.foundationid=fid;-- 没有into,编译报错,提示:Compilation Error: PLS-00428: an INTO clause is expected in this SELECT statement
3.在利用select…into…语法时,必须先确保数据库中有该条记录,否则会报出”no data found”异常。
可以在该语法之前,先利用select count(*) from 查看数据库中是否存在该记录,如果存在,再利用select…into…
4.在存储过程中,别名不能和字段名称相同,否则虽然编译可以通过,但在运行阶段会报错
–正确
select keynode into kn from APPFOUNDATION where appid=aid and foundationid=fid;
–错误
select af.keynode into kn from APPFOUNDATION af
where af.appid=appid and af.foundationid=foundationid;
– 运行阶段报错,提示ORA-01422:exact fetch returns more than requested number of rows
5.在存储过程中,关于出现null的问题
select sum(vcount) into fcount from A where bid=‘xxxxxx’;
如果A表中不存在bid=”xxxxxx”的记录,则fcount=null(即使fcount定义时设置了默认值,如:fcount number(8):=0依然无效,fcount还是会变成null),这样以后使用fcount时就可能有问题,所以在这里最好先判断一下:
if fcount is null then
fcount:=0;
end if;
来源:CSDN
作者:DominikMrz
链接:https://blog.csdn.net/qq_36580878/article/details/103774079