• 存储过程专题(Oracle)


    本文转自 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;
    凡哥,别他妈吹牛逼了
  • 相关阅读:
    字符编码及文件处理
    列表、元祖、字典及集合的内置方法
    数字类型、字符串及列表的内置方法
    流程控制(if while for)
    一些基本概念及数据类型
    编程语言的发展及变量
    python 入门基本知识
    叁拾贰(转)
    叁拾壹
    叁拾
  • 原文地址:https://www.cnblogs.com/sdlz/p/14949125.html
Copyright © 2020-2023  润新知