- create or replace procedure GetRecords(name_out out varchar2,age_in in varchar2) as
- begin
- select NAME into name_out from test where AGE = age_in;
- end;
- create or replace procedure insertRecord(UserID in varchar2, UserName in varchar2,UserAge in varchar2) is
- begin
- insert into test values (UserID, UserName, UserAge);
- end;
首先,在Oracle中創建了一個名爲TEST_SEQ的Sequence對象,SQL語句如下:
- create sequence TEST_SEQ
- minvalue 100
- maxvalue 999
- start with 102
- increment by 1
- nocache;
語法應該是比較易懂的,最小最大值分別用 minvalue,maxvalue表示,初始值是102(這個數字是動態變化的,我創建的時候設的是100,後因插入了2條數據後就自動增加了 2),increment當然就是步長了。在PL/SQL中可以用test_seq.nextval訪問下一個序列號,用 test_seq.currval訪問當前的序列號。
定義完了Sequence,接下來就是創建一個存儲過程InsertRecordWithSequence:
--這次我修改了test表的定義,和前面的示例不同。其中,UserID是PK。
- create or replace procedure InsertRecordWithSequence(UserID out number,UserName in varchar2,UserAge in number)
- is
- begin insert into test(id, name, age) --插入一條記錄,PK值從Sequece獲取
- values(test_seq.nextval, UserName, UserAge);
- /*返回PK值。注意Dual表的用法*/
- select test_seq.currval into UserID from dual;
- end InsertRecordWithSequence;
爲了讓存儲過程返回結果集,必須定義一個遊標變量作爲輸出參數。這和Sql Server中有着很大的不同!並且還要用到Oracle中“包”(Package)的概念,似乎有點繁瑣,但熟悉後也會覺得很方便。
關於“包”的概念,有很多內容可以參考,在此就不贅述了。首先,我創建了一個名爲TestPackage的包,包頭是這麼定義的:
- create or replace package TestPackage is
- type mycursor is ref cursor; -- 定義遊標變量
- procedure GetRecords(ret_cursor out mycursor); -- 定義過程,用遊標變量作爲返回參數
- end TestPackage;
- 包體是這麼定義的:
- create or replace package body TestPackage is
- /*過程體*/
- procedure GetRecords(ret_cursor out mycursor) as
- begin
- open ret_cursor for select * from test;
- end GetRecords;
- end TestPackage;
小結:
包是Oracle特有的概念,Sql Server中找不到相匹配的東西。在我看來,包有點像VC++的類,包頭就是.h文件,包體就是.cpp文件。包頭只負責定義,包體則負責具體實現。如果包返回多個遊標,則DataReader會按照您向參數集合中添加它們的順序來訪問這些遊標,而不是按照它們在過程中出現的順序來訪問。可使用 DataReader的NextResult()方法前進到下一個遊標。
- create or replace package TestPackage is
- type mycursor is ref cursor;
- procedure UpdateRecords(id_in in number,newName in varchar2,newAge in number);
- procedure SelectRecords(ret_cursor out mycursor);
- procedure DeleteRecords(id_in in number);
- procedure InsertRecords(name_in in varchar2, age_in in number);
- end TestPackage;
包體如下:
- create or replace package body TestPackage is
- procedure UpdateRecords(id_in in number, newName in varchar2, newAge in number) as
- begin
- update test set age = newAge, name = newName where id = id_in;
- end UpdateRecords;
- procedure SelectRecords(ret_cursor out mycursor) as
- begin
- open ret_cursor for select * from test;
- end SelectRecords;
- procedure DeleteRecords(id_in in number) as
- begin
- delete from test where id = id_in;
- end DeleteRecords;
- procedure InsertRecords(name_in in varchar2, age_in in number) as
- begin
- insert into test values (test_seq.nextval, name_in, age_in);
- --test_seq是一個已建的Sequence對象,請參照前面的示例
- end InsertRecords;
- end TestPackage;
TestPackage.SelectRecords
-------------------------------------------------------------------------------------------------------------------------------------------------------------
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存儲過程一例
By 凌雲志 發表於 2007-4-18 17:01:00
最近換了一個項目組,暈,要寫oracle的存儲過程,幸虧寫過一些db2的存儲過程,尚且有些經驗,不過oralce的pl/sql不大一樣,花費了一下午的時間寫了一個出來,測試編譯通過了,是爲記,以備以後查閱。
- CREATE OR REPLACE PACKAGE PY_PCKG_REFUND2 AS
- ------------------------------------------------------------------------
- -- Oracle 包
- ---國航支付平臺VISA退款
- -- 遊標定義:
- --
- -- 存儲過程定義:
- -- PY_WEBREFUND_VISA_PREPARE : VISA退款準備
- -- 最後修改人:dougq
- -- 最後修改日期:2007.4.17
- ------------------------------------------------------------------------
- PROCEDURE PY_WEBREFUND_VISA_PREPARE (
- in_serialNoStr IN VARCHAR2, --用"|"隔開的一組網上退款申請流水號
- in_session_operatorid IN VARCHAR2, --業務操作員
- out_return_code OUT VARCHAR2, --存儲過程返回碼
- out_visaInfoStr OUT VARCHAR2
- );
- END PY_PCKG_REFUND2;
- /
- CREATE OR REPLACE PACKAGE BODY PY_PCKG_REFUND2 AS
- PROCEDURE PY_WEBREFUND_VISA_PREPARE (
- in_serialNoStr IN VARCHAR2, --用"|"隔開的一組網上退款申請流水號
- in_session_operatorid IN VARCHAR2,--業務操作員
- out_return_code OUT VARCHAR2, --存儲過程返回碼
- out_visaInfoStr OUT VARCHAR2
- ) IS
- --變量聲明
- v_serialno VARCHAR2(20);--網上退款申請流水號
- v_refserialno VARCHAR2(20);--支付交易流水號
- v_tobankOrderNo VARCHAR2(30);--上送銀行的訂單號
- v_orderDate VARCHAR2(8);--訂單日期
- v_businessType VARCHAR2(10);--業務類型
- v_currType VARCHAR2(3);--訂單類型(ET-電子機票)
- v_merno VARCHAR2(15);--商戶號
- v_orderNo VARCHAR2(20);--商戶訂單號
- v_orderState VARCHAR2(2);
- v_refAmount NUMBER(15,2);--退款金額
- v_tranType VARCHAR(2);--交易類型
- v_bank VARCHAR2(10);--收單銀行
- v_date VARCHAR2 (8);--交易日期
- v_time VARCHAR2 (6);--交易時間
- v_datetime VARCHAR2 (14);--獲取的系統時間
- v_index_start NUMBER;
- v_index_end NUMBER;
- v_i NUMBER;
- BEGIN
- -- 初始化參數
- out_visaInfoStr := '';
- v_i := 1;
- v_index_start := 1;
- v_index_end := INSTR(in_serialNoStr,'|',1,1);
- v_refserialno := SUBSTR(in_serialNoStr, v_index_start, v_index_end-1);
- v_datetime := TO_CHAR (SYSDATE, 'yyyymmddhh24miss');
- v_date := SUBSTR (v_datetime, 1, 8);
- v_time := SUBSTR (v_datetime, 9, 14);
- --從退款請求表中查詢定單信息(商戶號、商戶訂單號、退款金額)
- WHILE v_index_end > 0 LOOP
- SELECT
- WEBR_MERNO,
- WEBR_ORDERNO,
- WEBR_AMOUNT,
- WEBR_SERIALNO,
- WEBR_REFUNDTYPE
- INTO
- v_merno,
- v_orderNo,
- v_refAmount,
- v_serialno,
- v_tranType
- FROM
- PY_WEB_REFUND
- WHERE
- WEBR_REFREQNO = v_refserialno;
- --將查詢到的數據組成串
- out_visaInfoStr := out_visaInfoStr || v_merno || '~' || v_orderNo || '~' || v_refAmount + '|';
- --爲下次循環做數據準備
- v_i := v_i + 1;
- v_index_start := v_index_end + 1;
- v_index_end := INSTR(in_serialNoStr,'|',1,v_i);
- IF v_index_end > 0 THEN
- v_refserialno := SUBSTR(in_serialNoStr, v_index_start, v_index_end - 1);
- END IF;
- --根據原支付流水號在流水錶中查詢該訂單的信息,包括原上送銀行或第三方的訂單號:WTRN_TOBANKORDERNO
- SELECT
- WTRN_TOBANKORDERNO,
- WTRN_ORDERNO,
- WTRN_ORDERDATE,
- WTRN_BUSINESSTYPE,
- WTRN_A**BANK,
- WTRN_TRANCURRTYPE
- INTO
- v_tobankOrderNo,
- v_orderNo,
- v_orderDate,
- v_businessType,
- v_bank,
- v_currType
- FROM PY_WEBPAY_VIEW
- WHERE WTRN_SERIALNO = v_serialno;
- --記錄流水錶(退款)
- INSERT INTO PY_WEBPAY_TRAN(
- WTRN_SERIALNO,
- WTRN_TRANTYPE,
- WTRN_ORIGSERIALNO,
- WTRN_ORDERNO,
- WTRN_ORDERDATE,
- WTRN_BUSINESSTYPE,
- WTRN_TRANCURRTYPE,
- WTRN_TRANAMOUNT,
- WTRN_A**BANK,
- WTRN_TRANSTATE,
- WTRN_TRANTIME,
- WTRN_TRANDATE,
- WTRN_MERNO,
- WTRN_TOBANKORDERNO
- )VALUES(
- v_refserialno, --和申請表的流水號相同,作爲參數傳人
- v_tranType,
- v_serialno, --原交易流水號,查詢退款申請表得到
- v_orderNo,
- v_orderDate,
- v_businessType,
- v_currType,
- v_refAmount,
- v_bank,
- '1',
- v_time,
- v_date,
- v_merno,
- v_tobankOrderNo --上送銀行的訂單號,查詢流水錶得到
- );
- --更新網上退款申請表
- UPDATE PY_WEB_REFUND
- SET
- WEBR_IFDISPOSED = '1',
- WEBR_DISPOSEDOPR = in_session_operatorid,
- WEBR_DISPOSEDDATE = v_datetime
- WHERE
- WEBR_REFREQNO = v_refserialno;
- --更新定單表
- IF v_tranType = '2' THEN
- v_orderState := '7';
- ELSE
- v_orderState := '10';
- END IF;
- UPDATE PY_ORDER
- SET
- ORD_ORDERSTATE = v_orderState
- WHERE
- ORD_ORDERNO = v_orderNo
- AND ORD_ORDERDATE = v_orderDate
- AND ORD_BUSINESSTYPE = v_businessType;
- END LOOP;
- -- 異常處理
- EXCEPTION
- WHEN OTHERS THEN
- ROLLBACK;
- out_return_code := '14001';
- RETURN;
- END;
- END PY_PCKG_REFUND2;
- /