329
技術社區[雲棲]
Oracle存儲過程基本語法
1.基本結構
CREATE OR REPLACE PROCEDURE 存儲過程名字
(
參數1 IN NUMBER,
參數2 IN NUMBER
) IS
變量1 INTEGER :=0;
變量2 DATE;
BEGIN
END 存儲過程名字
2.SELECT INTO STATEMENT
將select查詢的結果存入到變量中,可以同時將多個列存儲多個變量中,必須有一條
記錄,否則拋出異常(如果沒有記錄拋出NO_DATA_FOUND)
例子:
BEGIN
SELECT col1,col2 into 變量1,變量2 FROM typestruct where xxx;
EXCEPTION
WHEN NO_DATA_FOUND THEN
xxxx;
END;
...
3.IF 判斷
IF V_TEST=1 THEN
BEGIN
do something
END;
END IF;
4.while 循環
WHILE V_TEST=1 LOOP
BEGIN
XXXX
END;
END LOOP;
5.變量賦值
V_TEST := 123;
6.用for in 使用cursor
...
IS
CURSOR cur IS SELECT * FROM xxx;
BEGIN
FOR cur_result in cur LOOP
BEGIN
V_SUM :=cur_result.列名1+cur_result.列名2
END;
END LOOP;
END;
7.帶參數的cursor
CURSOR C_USER(C_ID NUMBER) IS SELECT NAME FROM USER WHERE TYPEID=C_ID;
OPEN C_USER(變量值);
LOOP
FETCH C_USER INTO V_NAME;
EXIT FETCH C_USER%NOTFOUND;
do something
END LOOP;
CLOSE C_USER;
8.用pl/sql developer debug
連接數據庫後建立一個Test WINDOW
在窗口輸入調用SP的代碼,F9開始debug,CTRL+N單步調試
通過一個實際的例子學習Oracle存儲過程
——創建存儲過程
CREATE OR REPLACE PROCEDURE xxxxxxxxxxx_p
(
--參數IN表示輸入參數,OUT表示輸入參數,類型可以使用任意Oracle中的合法類型。
is_ym IN CHAR
)
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)/10000usd_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;
=========================================
幾個對job執行時間設定的例子,對於oracle日誌設定不熟悉,借鑒一下:
描述 |
INTERVAL參數值 |
每天午夜12點 |
'TRUNC(SYSDATE + 1)' |
每天早上8點30分 |
'TRUNC(SYSDATE + 1) + (8*60+30)/(24*60)' |
每星期二中午12點 |
'NEXT_DAY(TRUNC(SYSDATE ), ''TUESDAY'' ) + 12/24' |
每個月第一天的午夜12點 |
'TRUNC(LAST_DAY(SYSDATE ) + 1)' |
每個季度最後一天的晚上11點 |
'TRUNC(ADD_MONTHS(SYSDATE + 2/24, 3 ), 'Q' ) -1/24' |
每星期六和日早上6點10分 |
'TRUNC(LEAST(NEXT_DAY(SYSDATE, ''SATURDAY"), NEXT_DAY(SYSDATE, "SUNDAY"))) + (6×60+10)/(24×60)' |
最後更新:2017-04-03 16:49:03