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