Oracle存儲過程實用案例

存儲過程並不是是應用程序的首選,但在一些其他場景如造數,批量處理數據的時候還用的上,分享一波腳本,當做工具就好。

1、獲取一個表的所有列名

-- Created on 2014/5/5 by ADMIN1 
declare 
  -- Local variables here
  i NUMBER := 0;
  CURSOR cur IS SELECT column_name FROM USER_COL_COMMENTS WHERE table_name = 'TABLE';
  cols CLOB;
begin
  -- Test statements here
  FOR col IN cur LOOP
    IF i <> 0 THEN 
      cols := cols ||',';
    END IF;
    i := 1;
    cols := cols || col.COLUMN_NAME;
  END LOOP;
  DBMS_OUTPUT.PUT_LINE(cols);
end;

2、循環的幾種方式

CREATE OR REPLACE PROCEDURE P_LOOP
AS
V_COUNT NUMBER DEFAULT 0;
CURSOR V_CURSOR IS SELECT * FROM JOBS;
V_JOB JOBS%ROWTYPE;

BEGIN
  --------------------------------------LOOP
  LOOP
    V_COUNT := V_COUNT +1;
    EXIT WHEN V_COUNT>=5;
  END LOOP;
  DBMS_OUTPUT.PUT_LINE(V_COUNT);

  -------------------------------------CURSOR
  ---------------%FOUND 可從遊標中取出一條記錄
  ---------------%NOTFOUND 不能從遊標中再取出記錄
  ---------------%ISOPEN 遊標已經打開
  ---------------%ROWCOUNT 迄今爲止從遊標中取出的行數
  OPEN V_CURSOR;
  LOOP
    FETCH V_CURSOR INTO V_JOB;
    EXIT WHEN V_CURSOR%NOTFOUND;

    DBMS_OUTPUT.PUT_LINE(V_JOB.JOB_ID || ','||V_JOB.JOB_TITLE||V_CURSOR%ROWCOUNT );
  END LOOP;
  CLOSE V_CURSOR;

  ----------------------------------FOR
  FOR I IN 1..5 LOOP
    DBMS_OUTPUT.PUT_LINE('FOR...................'||I);
  END LOOP;

  -------------------------------FOR + CURSOR
  FOR ITEM IN V_CURSOR LOOP
     DBMS_OUTPUT.PUT_LINE(ITEM.JOB_ID || ','||ITEM.JOB_TITLE);
  END LOOP;

  -------------------------------WHILE
  V_COUNT:=0;
  WHILE V_COUNT <5
    LOOP
      V_COUNT := V_COUNT +1;
      DBMS_OUTPUT.PUT_LINE(V_COUNT);
    END LOOP;


END;
/

3、大數據量插入

CREATE OR REPLACE PROCEDURE P_BIGDATA_INSERT(P_TABLE_NAME   IN VARCHAR2, --目標表
                                             P_TABLE_COLUMN IN VARCHAR2, --目標字段
                                             P_TABLE_SELECT IN VARCHAR2, --SELECT 查詢語句
                                             RETURN_RESULT   OUT NUMBER --返回的結果1,表示成功,0表示失敗
                                             ) AS
  /** 
   對大數據量的表進行分批提交
  */
  RUNTIME NUMBER;
  I       NUMBER;
  AMOUNT  NUMBER;
  S_SQL   VARCHAR2(5000);
  P_SIZE NUMBER := 5000;
  Q_SQL CLOB;
BEGIN
  RETURN_RESULT := 0; --開始初始化爲0
  --核必邏輯內容,可根據具體的業務邏輯來自定義
  S_SQL := 'select count(1) from (' || P_TABLE_SELECT || ')';
  EXECUTE IMMEDIATE S_SQL INTO AMOUNT;

  --每P_SIZE提交一次
  RUNTIME := AMOUNT MOD P_SIZE;
  IF (RUNTIME > 0) THEN
    RUNTIME := 1 + TRUNC(AMOUNT / P_SIZE);
  ELSIF (RUNTIME = 0) THEN
    RUNTIME := 0 + TRUNC(AMOUNT / P_SIZE);
  END IF;


 --核必邏輯內容,可根據具體的業務邏輯來自定義
  FOR I IN 1 .. RUNTIME LOOP
  Q_SQL:= 'insert into ' || P_TABLE_NAME || ' (' ||
                      P_TABLE_COLUMN || ')  
     select ' || P_TABLE_COLUMN || ' from (select selectSec.*, rownum rownumType  
          from (' || P_TABLE_SELECT ||') selectSec  
         WHERE ROWNUM <= ' || I * P_SIZE || ')  
          WHERE rownumType > ' || (I - 1) * P_SIZE;
--    DBMS_OUTPUT.PUT_LINE(Q_SQL);
    EXECUTE IMMEDIATE Q_SQL;
    --提交
    COMMIT;
  END LOOP;
  RETURN_RESULT := 1;
  RETURN;
EXCEPTION
  WHEN OTHERS THEN
    RETURN_RESULT := 0;
    ROLLBACK;
    --dbms_output.put_line('執行出現異常,錯誤碼='|| SQLCODE || ',錯誤描述=' || SUBSTR(SQLERRM, 1, 100));
    RAISE;

    RETURN;
END;


4、大數據量刪除

CREATE OR REPLACE PROCEDURE P_DEL_BIGDATA --分批提交刪除
(P_SQL IN VARCHAR2 --SQL語句,示例:P_DEL_BIGDATA('delete from table where rownum <= 10');
 ) AS
BEGIN

  /** 循環執行*/
  WHILE 1 = 1 LOOP
    EXECUTE IMMEDIATE P_SQL;
    IF SQL%NOTFOUND THEN
      EXIT;
    END IF;
    COMMIT;
  END LOOP;
  COMMIT;
END;

5、存儲過程中的異常處理

CREATE OR REPLACE PROCEDURE P_EXCEPTION
/**
1、預定義異常
2、自定義異常

自定義異常編號 –20,000 到 –20,999 
自定義異常消息  2048 byte
*/
AS
v_name employees.first_name%TYPE;
exp1 EXCEPTION;
--PRAGMA EXCEPTION_INIT(exp1, -20000);
BEGIN

  SELECT first_name INTO v_name FROM employees e WHERE e.employee_id = 100;
  IF SQL%FOUND THEN
    --拋出異常 方式一
    --RAISE exp1;

    --方式二
    RAISE_APPLICATION_ERROR(-20000,'異常');
  END IF;

EXCEPTION
  WHEN exp1 THEN
    DBMS_OUTPUT.PUT_LINE(SQLCODE||'------>'||SQLERRM);
  WHEN OTHERS THEN
  DBMS_OUTPUT.PUT_LINE(SQLCODE||'->'||SQLERRM);
END;
/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章