zoukankan      html  css  js  c++  java
  • 存储过程专题(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;
    凡哥,别他妈吹牛逼了
  • 相关阅读:
    129 01 Android 零基础入门 02 Java面向对象 06 Java单例模式 03 饿汉模式 VS 懒汉模式 02 懒汉式的代码实现
    128 01 Android 零基础入门 02 Java面向对象 06 Java单例模式 03 饿汉模式 VS 懒汉模式 01 饿汉式的代码实现
    127 01 Android 零基础入门 02 Java面向对象 06 Java单例模式 02 单例模式概述 01 单例模式的定义和作用
    126 01 Android 零基础入门 02 Java面向对象 06 Java单例模式 01 设计模式概述 01 设计模式简介
    125 01 Android 零基础入门 02 Java面向对象 05 Java继承(下)05 Java继承(下)总结 01 Java继承(下)知识点总结
    leetcode-----121. 买卖股票的最佳时机
    leetcode-----104. 二叉树的最大深度
    Json串的字段如果和类中字段不一致,如何映射、转换?
    Mybatis-Plus的Service方法使用 之 泛型方法default <V> List<V> listObjs(Function<? super Object, V> mapper)
    模糊查询
  • 原文地址:https://www.cnblogs.com/sdlz/p/14949125.html
Copyright © 2011-2022 走看看