本文转自 https://www.cnblogs.com/lukelook/p/9600407.html,感谢博主 豆豆DE思念 整理分享。
1.Oracle 存储过程基本格式
最简单的版本 is as 都可以
create or replace procedure create_test as begin dbms_output.put_line('1234'); end create_test;
调用
-- 1.如果是命令窗口就用exec 存储过程名,举个栗子: EXEC procedure;--procedure是存储过程名 -- 2.如果是PL/SQL窗口就用 begin 存储过程名 end; 举个栗子: begin procedure;--procedure是存储过程名 end; -- 或者 execute proname; -- 3.如果是程序中调用就用 call 存储过程名 ,举个栗子: hibernateDao.excuteSqlUpdate("{Call proc_stuInfo()}");//存储过程proc_stuInfo
基本模版
create or replace PROCEDURE CREATE_TEST( INPUT IN VARCHAR2, OUTPUT OUT VARCHAR2 ) AS MSG VARCHAR2(20) :='小红'; BEGIN DBMS_OUTPUT.PUT_LINE(MSG); INSERT INTO TEST VALUES (INPUT,MSG); END CREATE_TEST;
调用
declare output VARCHAR2(20); BEGIN CREATE_TEST('15',output); end;
注意在调用不是当前用户创建的一定要加上用户.
declare output VARCHAR2(20); BEGIN look.CREATE_TEST('15',output); end;
标准版本 添加异常处理模块和输入输出控制:
CREATE OR REPLACE PROCEDURE CREATE_TEST( INPUT IN VARCHAR2, OUT_CODE OUT INTEGER, OUT_MSG OUT VARCHAR2 ) AS MSG VARCHAR2(20) :='小红'; BEGIN DBMS_OUTPUT.PUT_LINE(MSG); INSERT INTO TEST VALUES (INPUT,MSG); OUT_CODE := SQLCODE; OUT_MSG := 'OK'; EXCEPTION WHEN OTHERS THEN OUT_CODE := SQLCODE;--以前根据这个标识来判断过程是否执行成功 OUT_MSG := 'test:' || SQLERRM; DBMS_OUTPUT.PUT_LINE(OUT_CODE || ':' || OUT_MSG); RAISE;--用于抛出异常 END CREATE_TEST;
SQLCODE SQLERRM 是不能直接在sql语句中使用,必须先将其赋给变量后;
自定义异常
CREATE OR REPLACE PROCEDURE CREATE_TEST( INPUT IN VARCHAR2, OUT_CODE OUT INTEGER, OUT_MSG OUT VARCHAR2 ) AS EXC EXCEPTION; BEGIN IF(INPUT ='7') THEN RAISE EXC; --raise_application_error(-20000,'输入值不能为7!'); END IF; OUT_CODE := SQLCODE; OUT_MSG := 'OK'; EXCEPTION WHEN EXC THEN DBMS_OUTPUT.PUT_LINE('====进入自定义异常模块===='); OUT_CODE := SQLCODE;--以前根据这个标识来判断过程是否执行成功 OUT_MSG := 'test:' || SQLERRM; DBMS_OUTPUT.PUT_LINE(OUT_CODE || ':' || OUT_MSG); RAISE;--用于抛出异常 WHEN OTHERS THEN OUT_CODE := SQLCODE;--以前根据这个标识来判断过程是否执行成功 OUT_MSG := 'test:' || SQLERRM; DBMS_OUTPUT.PUT_LINE(OUT_CODE || ':' || OUT_MSG); RAISE;--用于抛出异常 END CREATE_TEST;
或者
create or replace PROCEDURE CREATE_TEST( INPUT IN VARCHAR2, OUT_CODE OUT INTEGER, OUT_MSG OUT VARCHAR2 ) AS EXC EXCEPTION; BEGIN IF(INPUT ='7') THEN --RAISE EXC; raise_application_error(-20000,'输入值不能为7!'); END IF; OUT_CODE := SQLCODE; OUT_MSG := 'OK'; EXCEPTION WHEN OTHERS THEN OUT_CODE := SQLCODE;--以前根据这个标识来判断过程是否执行成功 OUT_MSG := 'test:' || SQLERRM; DBMS_OUTPUT.PUT_LINE(OUT_CODE || ':' || OUT_MSG); RAISE;--用于抛出异常 END CREATE_TEST;
模版1
--创建存储过程 CREATE OR REPLACE PROCEDURE xxxxxxxxxxx_p ( --参数IN表示输入参数, --OUT表示输入参数,类型可以使用任意Oracle中的合法类型。 is_ym IN VARCHAR2 v_out OUT VARCHAR2) AS --定义变量 vs_msg VARCHAR2(4000); --错误信息变量 vs_ym_beg CHAR(6); --起始月份 vs_ym_end CHAR(6); --终止月份 vs_ym_sn_beg CHAR(6); --同期起始月份 vs_ym_sn_end CHAR(6); --同期终止月份 --定义游标(简单的说就是一个可以遍历的结果集) CURSOR cur_1 IS SELECT area_code,CMCODE,SUM(rmb_amt)/10000 rmb_amt_sn,SUM(usd_amt)/10000 usd_amt_sn FROM BGD_AREA_CM_M_BASE_T WHERE ym >= vs_ym_sn_beg AND ym <= vs_ym_sn_end GROUP BY area_code,CMCODE; BEGIN --用输入参数给变量赋初值,用到了Oralce的SUBSTR TO_CHAR ADD_MONTHS TO_DATE 等很常用的函数。 vs_ym_beg := SUBSTR(is_ym,1,6); vs_ym_end := SUBSTR(is_ym,7,6); vs_ym_sn_beg := TO_CHAR(ADD_MONTHS(TO_DATE(vs_ym_beg,'yyyymm'), -12),'yyyymm'); vs_ym_sn_end := TO_CHAR(ADD_MONTHS(TO_DATE(vs_ym_end,'yyyymm'), -12),'yyyymm'); --先删除表中特定条件的数据。 DELETE FROM xxxxxxxxxxx_T WHERE ym = is_ym; --然后用内置的DBMS_OUTPUT对象的put_line方法打印出影响的记录行数,其中用到一个系统变量SQL%rowcount DBMS_OUTPUT.put_line('del上月记录='||SQL%rowcount||'条'); INSERT INTO xxxxxxxxxxx_T(area_code,ym,CMCODE,rmb_amt,usd_amt) SELECT area_code,is_ym,CMCODE,SUM(rmb_amt)/10000,SUM(usd_amt)/10000 FROM BGD_AREA_CM_M_BASE_T WHERE ym >= vs_ym_beg AND ym <= vs_ym_end GROUP BY area_code,CMCODE; DBMS_OUTPUT.put_line('ins当月记录='||SQL%rowcount||'条'); --遍历游标处理后更新到表。遍历游标有几种方法,用for语句是其中比较直观的一种。 FOR rec IN cur_1 LOOP UPDATE xxxxxxxxxxx_T SET rmb_amt_sn = rec.rmb_amt_sn,usd_amt_sn = rec.usd_amt_sn WHERE area_code = rec.area_code AND CMCODE = rec.CMCODE AND ym = is_ym; END LOOP; COMMIT; --错误处理部分。OTHERS表示除了声明外的任意错误。SQLERRM是系统内置变量保存了当前错误的详细信息。 EXCEPTION WHEN OTHERS THEN vs_msg := 'ERROR IN xxxxxxxxxxx_p('||is_ym||'):'||SUBSTR(SQLERRM,1,500); ROLLBACK; --把当前错误记录进日志表。 INSERT INTO LOG_INFO(proc_name,error_info,op_date) VALUES('xxxxxxxxxxx_p',vs_msg,SYSDATE); COMMIT; RETURN; END;
模版2
--模板二: --ORACLE存储过程实例: CREATE OR REPLACE PROCEDURE CL_24_MONTHS_STATUS --(无输入/输出参数) IS --存储过程开始 BEGIN DECLARE --声明变量 V_OP_NUM CHAR(20); V_START_DATE DATE; V_END_DATE DATE; V_COUNT NUMBER; V_COUNT1 NUMBER; V_24MONTHS_FLAG VARCHAR(24); FOR rec IN cur_1 LOOP UPDATE xxxxxxxxxxx_T SET rmb_amt_sn = rec.rmb_amt_sn,usd_amt_sn = rec.usd_amt_sn WHERE area_code = rec.area_code AND CMCODE = rec.CMCODE AND ym = is_ym; END LOOP; COMMIT; --错误处理部分。OTHERS表示除了声明外的任意错误。SQLERRM是系统内置变量保存了当前错误的详细信息。 EXCEPTION WHEN OTHERS THEN vs_msg := 'ERROR IN xxxxxxxxxxx_p('||is_ym||'):'||SUBSTR(SQLERRM,1,500); ROLLBACK; --把当前错误记录进日志表。 INSERT INTO LOG_INFO(proc_name,error_info,op_date) VALUES('xxxxxxxxxxx_p',vs_msg,SYSDATE); COMMIT; RETURN; END;
模版3
--模板二: --ORACLE存储过程实例: CREATE OR REPLACE PROCEDURE CL_24_MONTHS_STATUS --(无输入/输出参数) IS --存储过程开始 BEGIN DECLARE --声明变量 V_OP_NUM CHAR(20); V_START_DATE DATE; V_END_DATE DATE; V_COUNT NUMBER; V_COUNT1 NUMBER; V_24MONTHS_FLAG VARCHAR(24); V_DATE_OPENED DATE; V_MATURE_DATE DATE; V_OVERDUE NUMBER; V_STATUS CHAR(1); V_REPORTDATE DATE; V_BILLING_DATE1 DATE; V_BILLING_DATE2 DATE; --声明游标 CURSOR OVERDUE_CURSOR IS SELECT OP_NUM,DATE_OPENED,MATURE_DATE,STATUS FROM CL_VALID_CONTRACT WHERE TERM_FREQ<>'5' ORDER BY OP_NUM; --程序体开始 BEGIN OPEN OVERDUE_CURSOR; SELECT REPORTDATE INTO V_REPORTDATE FROM T_ETLDATE; DELETE FROM CL_MONTHS24_STATUS_TOTAL; LOOP V_24MONTHS_FLAG:=''; V_END_DATE:=V_REPORTDATE; FETCH OVERDUE_CURSOR INTO V_OP_NUM,V_DATE_OPENED,V_MATURE_DATE,V_STATUS; --计算需要计算的最早和最晚月份 IF ADD_MONTHS(V_END_DATE,-24)<V_DATE_OPENED THEN V_START_DATE:=LAST_DAY(V_DATE_OPENED); ELSE V_START_DATE:=ADD_MONTHS(V_END_DATE,-23); END IF; EXIT WHEN OVERDUE_CURSOR%NOTFOUND; LOOP EXIT WHEN V_END_DATE <= V_START_DATE; --计算前23个月的还款状态 SELECT NVL(MAX(BILLING_DATE),LAST_DAY(V_START_DATE)) INTO V_BILLING_DATE1 FROM CL_VALID_BALANCE B WHERE OP_NUM=V_OP_NUM AND LAST_DAY(BILLING_DATE)=LAST_DAY(V_START_DATE); SELECT NVL(MAX(BILLING_DATE),LAST_DAY(ADD_MONTHS(V_START_DATE,-1))) INTO V_BILLING_DATE2 FROM CL_VALID_BALANCE B WHERE OP_NUM=V_OP_NUM AND LAST_DAY(BILLING_DATE)=LAST_DAY(ADD_MONTHS(V_START_DATE,-1)); SELECT COUNT(*) INTO V_COUNT FROM CL_VALID_BALANCE WHERE OP_NUM=V_OP_NUM AND BILLING_DATE BETWEEN V_BILLING_DATE2+1 AND V_BILLING_DATE1; SELECT NVL(MAX(V_BILLING_DATE1-BILLING_DATE+1),-1) INTO V_COUNT1 FROM CL_VALID_OVERDUE WHERE OP_NUM=V_OP_NUM AND V_BILLING_DATE1 BETWEEN BILLING_DATE AND ACTUAL_DATE-1; IF V_COUNT=0 AND V_COUNT1<=0 THEN V_24MONTHS_FLAG:=CONCAT(V_24MONTHS_FLAG,'*'); ELSIF V_COUNT1<=0 THEN V_24MONTHS_FLAG:=CONCAT(V_24MONTHS_FLAG,'N'); ELSIF TRUNC((V_COUNT1-1)/30+1)<8 THEN V_24MONTHS_FLAG:=CONCAT(V_24MONTHS_FLAG,TRUNC((V_COUNT1-1)/30+1)); ELSE V_24MONTHS_FLAG:=CONCAT(V_24MONTHS_FLAG,'7'); END IF; V_START_DATE:=ADD_MONTHS(V_START_DATE,1); END LOOP; --计算最后一个月的还款状态 SELECT NVL(MAX(BILLING_DATE),LAST_DAY(V_START_DATE)) INTO V_BILLING_DATE1 FROM CL_VALID_BALANCE B WHERE OP_NUM=V_OP_NUM AND LAST_DAY(BILLING_DATE)=LAST_DAY(V_START_DATE); SELECT NVL(MAX(BILLING_DATE),LAST_DAY(ADD_MONTHS(V_START_DATE,-1))) INTO V_BILLING_DATE2 FROM CL_VALID_BALANCE B WHERE OP_NUM=V_OP_NUM AND LAST_DAY(BILLING_DATE)=LAST_DAY(ADD_MONTHS(V_START_DATE,-1)); SELECT COUNT(*) INTO V_COUNT FROM CL_VALID_BALANCE WHERE OP_NUM=V_OP_NUM AND BILLING_DATE BETWEEN V_BILLING_DATE2+1 AND V_BILLING_DATE1; SELECT NVL(MAX(V_BILLING_DATE1-BILLING_DATE+1),-1) INTO V_COUNT1 FROM CL_VALID_OVERDUE WHERE OP_NUM=V_OP_NUM AND V_BILLING_DATE1 BETWEEN BILLING_DATE AND ACTUAL_DATE-1; IF V_STATUS='9' THEN V_24MONTHS_FLAG:=CONCAT(V_24MONTHS_FLAG,'C'); ELSIF V_COUNT=0 AND V_COUNT1<=0 THEN V_24MONTHS_FLAG:=CONCAT(V_24MONTHS_FLAG,'*'); ELSIF V_COUNT1<=0 THEN V_24MONTHS_FLAG:=CONCAT(V_24MONTHS_FLAG,'N'); ELSIF TRUNC((V_COUNT1-1)/30+1)<8 THEN V_24MONTHS_FLAG:=CONCAT(V_24MONTHS_FLAG,TRUNC((V_COUNT1-1)/30+1)); ELSE V_24MONTHS_FLAG:=CONCAT(V_24MONTHS_FLAG,'7'); END IF; INSERT INTO CL_MONTHS24_STATUS_TOTAL VALUES (V_OP_NUM,LPAD(V_24MONTHS_FLAG,24,'/')); COMMIT; END LOOP; --关闭游标 CLOSE OVERDUE_CURSOR; --程序体结束 END; --存储过程结束 END;