Oracle-procedure/cursor解讀
阿新 • • 發佈:2019-01-08
概述
procedure系列
procedure概述
儲存過程( Stored Procedure )是一組為了完成特定功能的 SQL 語句集,經編譯後儲存在資料庫中。
使用者通過指定儲存過程的名字並給出引數(如果該儲存過程帶有引數)來執行它。
儲存過程是由流控制和 SQL 語句書寫的過程,這個過程經編譯和優化後儲存在資料庫伺服器中,應用程式使用時只要呼叫即可。
在 ORACLE 中,若干個有聯絡的過程可以組合在一起構成程式包。
procedure優點
儲存過程只在創造時進行編譯,以後每次執行儲存過程都不需再重新編譯,而一般 SQL 語句每執行一次就編譯一次,所以使用儲存過程可提高資料庫執行速度。
當對資料庫進行復雜操作時(如對多個表進行 Update、Insert、Query、Delete時),可將此複雜操作用儲存過程封裝起來與資料庫提供的事務處理結合一起使用。
儲存過程可以重複使用,可減少資料庫開發人員的工作量。
安全性高,可設定只有某使用者才具有對指定儲存過程的使用權。
和function的區別
procedure栗子
CREATE OR REPLACE procedure proc_trade(
v_tradeid in number, --交易id
v_third_ip in varchar2, --第三方ip
v_third_time in date, --第三方完成時間
v_thire_state in number, --第三方狀態
o_result out number, --返回值
o_detail out varchar2 --詳細描述
) as
-- 定義變數
v_error varchar2(500);
begin
--對變數賦值
o_result := 0;
o_detail := '驗證失敗';
--業務邏輯處理
if v_tradeid > 100 then
insert into table_name (.. .) values (.. .);
commit;
elsif v_tradeid < 100 and v_tradeid > 50 then
insert into table_name (.. .) values (.. .);
commit;
else
goto log;
end if;
--跳轉標誌符,名稱自己指定
<<log>>
o_result := 1;
--捕獲異常
exception
when no_data_found then
result := 2;
when dup_val_on_index then
result := 3;
when others then
result := -1;
end proc_trade;
引數型別可以自己指定,這種寫法可行,但是最好使用%type 來獲取引數的型別(table_name.column_name%TYPE)。 這樣就不會出現引數型別的錯誤。
儲存過程中的迴圈
for … in … loop 迴圈
迴圈遍歷遊標
示例1:
CREATE OR REPLACE PROCEDURE proc_test AS
CURSOR c1 IS
SELECT * FROM dat_trade;
BEGIN
FOR x IN c1 LOOP
DBMS_OUTPUT.put_line(x.id);
END LOOP;
END proc_test;
示例 2:
CREATE OR REPLACE PROCEDURE proc_test AS
BEGIN
FOR x IN (SELECT power_id FROM sys_power) LOOP
DBMS_OUTPUT.put_line(x.power_id);
END LOOP;
END proc_test;
根據數值進行迴圈
栗子一
CREATE OR REPLACE PROCEDURE proc_test AS
BEGIN
for x in 1 .. 100 loop
dbms_output.put_line(x);
end loop;
END proc_test;
栗子2:在過程裡指定輸入引數 v_num. 在呼叫過程時指定迴圈次數。
CREATE OR REPLACE PROCEDURE proc_test(v_num IN NUMBER) AS
BEGIN
FOR x IN 1 .. v_num LOOP
DBMS_OUTPUT.put_line(x);
END LOOP;
END proc_test;
loop 迴圈
LOOP
DELETE FROM orders
WHERE senddate < TO_CHAR (ADD_MONTHS (SYSDATE, -3),
'yyyy-mm-dd')
AND ROWNUM < 1000;
EXIT WHEN SQL%ROWCOUNT < 1;
COMMIT;
END LOOP;
這 裡 的 SQL%ROWCOUNT 是 隱 士 遊 標 。 除 了 這 個 , 還 有 其 他 幾
個: %found, %notfound, %isopen。
while 迴圈
CREATE OR REPLACE PROCEDURE proc_test(v_num IN NUMBER)
AS
i NUMBER := 1;
BEGIN
WHILE i < v_num LOOP
BEGIN
i := i + 1;
DBMS_OUTPUT.put_line(i);
END;
END LOOP;
END proc_test;
儲存過程中的判斷
if … elsif … else … 判斷
CREATE OR REPLACE PROCEDURE proc_test(v_num IN NUMBER) AS
BEGIN
IF v_num < 10 THEN
DBMS_OUTPUT.put_line(v_num);
ELSIF v_num > 10 AND v_num < 50 THEN
DBMS_OUTPUT.put_line(v_num - 10);
ELSE
DBMS_OUTPUT.put_line(v_num - 50);
END IF;
END proc_test;
case … when … end case 判斷
CREATE OR REPLACE PROCEDURE proc_test(v_num IN NUMBER) AS
BEGIN
case v_num
when 1 then
DBMS_OUTPUT.put_line(v_num);
when 2 then
DBMS_OUTPUT.put_line(v_num);
when 3 then
DBMS_OUTPUT.put_line(v_num);
else
null;
end case;
END proc_test;
遊標
Cursor 型遊標(不能用於引數傳遞)
CREATE OR REPLACE PROCEDURE proc_test AS
CURSOR c1 IS
SELECT * FROM dat_trade;
BEGIN
FOR x IN c1 LOOP
DBMS_OUTPUT.put_line(x.id);
END LOOP;
END proc_test;
SYS_REFCURSOR 型遊標
該遊標是 Oracle 預先定義的遊標,可作出引數進行傳遞。
SYS_REFCURSOR 只能通過 OPEN 方法來開啟和賦值
我們可以使用這種類似的遊標來返回一個結果集:
CREATE OR REPLACE procedure proc_test(
checknum in number, --每次返回的資料量
ref_cursor out sys_refcursor --返回的結果集,遊標
) as
begin
open ref_cursor for
select *
from (select * from dat_trade where state = 41 order by id)
where rownum < checknum;
end proc_test;
SYS_REFCURSOR 中可使用四個狀態屬性:
- ( 1) . %NOTFOUND(未找到記錄資訊)
- ( 2) . %FOUND(找到記錄資訊)
- ( 3) . %ROWCOUNT(然後當前遊標所指向的行位置)
- (4). %ISOPEN(是否開啟)
CREATE OR REPLACE PROCEDURE proc_test(
checknum IN NUMBER, --每次返回的資料量
ref_cursor OUT sys_refcursor --返回的結果集,遊標
) AS
t_tmp table_name%ROWTYPE;
BEGIN
OPEN ref_cursor FOR
SELECT *
FROM (SELECT * FROM table_name WHERE state = 41 ORDER BY id)
WHERE ROWNUM < checknum;
--循環遊標
LOOP
FETCH ref_cursor
INTO t_tmp;
EXIT WHEN ref_cursor%NOTFOUND;
-- DBMS_OUTPUT.put_line (t_tmp.id);
UPDATE table_name SET state = 53 WHERE id = t_tmp.id;
COMMIT;
END LOOP;
CLOSE ref_cursor;
END proc_test;