当前位置:Gxlcms > mysql > Oracle存储过程实例

Oracle存储过程实例

时间:2021-07-01 10:21:17 帮助过:29人阅读

createorreplaceprocedureGetRecords(name_outoutvarchar2,age_ininvarchar2)as begin selectNAMEintoname_outfromtestwhereAGE=age_in; end; createorreplaceprocedureinsertRecord(UserIDinvarchar2,UserNameinvarchar2,UserAgeinvarchar2)is begin insert

  1. create or replace procedure GetRecords(name_out out varchar2,age_in in varchar2) as
  2. begin
  3. select NAME into name_out from test where AGE = age_in;
  4. end;
  5. create or replace procedure insertRecord(UserID in varchar2, UserName in varchar2,UserAge in varchar2) is
  6. begin
  7. insert into test values (UserID, UserName, UserAge);
  8. end;

首先,在Oracle中创建了一个名为TEST_SEQ的Sequence对象,SQL语句如下:

Java代码

  1. create sequence TEST_SEQ
  2. minvalue 100
  3. maxvalue 999
  4. start with 102
  5. increment by 1
  6. nocache;

语法应该是比较易懂的,最小最大值分别用minvalue,maxvalue表示,初始值是102(这个数字是动态变化的,我创建的时候设的是100,后因插入了2条数据后就自动增加了2),increment当然就是步长了。在PL/SQL中可以用test_seq.nextval访问下一个序列号,用test_seq.currval访问当前的序列号。

定义完了Sequence,接下来就是创建一个存储过程InsertRecordWithSequence:

--这次我修改了test表的定义,和前面的示例不同。其中,UserID是PK。

Java代码

  1. create or replace procedure InsertRecordWithSequence(UserID out number,UserName in varchar2,UserAge in number)
  2. is
  3. begin insert into test(id, name, age) --插入一条记录,PK值从Sequece获取
  4. values(test_seq.nextval, UserName, UserAge);
  5. /*返回PK值。注意Dual表的用法*/
  6. select test_seq.currval into UserID from dual;
  7. end InsertRecordWithSequence;

为了让存储过程返回结果集,必须定义一个游标变量作为输出参数。这和Sql Server中有着很大的不同!并且还要用到Oracle中“包”(Package)的概念,似乎有点繁琐,但熟悉后也会觉得很方便。

关于“包”的概念,有很多内容可以参考,在此就不赘述了。首先,我创建了一个名为TestPackage的包,包头是这么定义的:

Java代码

  1. create or replace package TestPackage is
  2. type mycursor is ref cursor; -- 定义游标变量
  3. procedure GetRecords(ret_cursor out mycursor); -- 定义过程,用游标变量作为返回参数
  4. end TestPackage;
  5. 包体是这么定义的:
  6. create or replace package body TestPackage is
  7. /*过程体*/
  8. procedure GetRecords(ret_cursor out mycursor) as
  9. begin
  10. open ret_cursor for select * from test;
  11. end GetRecords;
  12. end TestPackage;

小结:

包是Oracle特有的概念,Sql Server中找不到相匹配的东西。在我看来,包有点像VC++的类,包头就是.h文件,包体就是.cpp文件。包头只负责定义,包体则负责具体实现。如果包返回多个游标,则DataReader会按照您向参数集合中添加它们的顺序来访问这些游标,而不是按照它们在过程中出现的顺序来访问。可使用DataReader的NextResult()方法前进到下一个游标。

Java代码

  1. create or replace package TestPackage is
  2. type mycursor is ref cursor;
  3. procedure UpdateRecords(id_in in number,newName in varchar2,newAge in number);
  4. procedure SelectRecords(ret_cursor out mycursor);
  5. procedure DeleteRecords(id_in in number);
  6. procedure InsertRecords(name_in in varchar2, age_in in number);
  7. end TestPackage;

包体如下:

Java代码

  1. create or replace package body TestPackage is
  2. procedure UpdateRecords(id_in in number, newName in varchar2, newAge in number) as
  3. begin
  4. update test set age = newAge, name = newName where id = id_in;
  5. end UpdateRecords;
  6. procedure SelectRecords(ret_cursor out mycursor) as
  7. begin
  8. open ret_cursor for select * from test;
  9. end SelectRecords;
  10. procedure DeleteRecords(id_in in number) as
  11. begin
  12. delete from test where id = id_in;
  13. end DeleteRecords;
  14. procedure InsertRecords(name_in in varchar2, age_in in number) as
  15. begin
  16. insert into test values (test_seq.nextval, name_in, age_in);
  17. --test_seq是一个已建的Sequence对象,请参照前面的示例
  18. end InsertRecords;
  19. 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不大一样,花费了一下午的时间写了一个出来,测试编译通过了,是为记,以备以后查阅。

Java代码

  1. CREATE OR REPLACE PACKAGE PY_PCKG_REFUND2 AS
  2. ------------------------------------------------------------------------
  3. -- Oracle 包
  4. ---国航支付平台VISA退款
  5. -- 游标定义:
  6. --
  7. -- 存储过程定义:
  8. -- PY_WEBREFUND_VISA_PREPARE : VISA退款准备
  9. -- 最后修改人:dougq
  10. -- 最后修改日期:2007.4.17
  11. ------------------------------------------------------------------------
  12. PROCEDURE PY_WEBREFUND_VISA_PREPARE (
  13. in_serialNoStr IN VARCHAR2, --用"|"隔开的一组网上退款申请流水号
  14. in_session_operatorid IN VARCHAR2, --业务操作员
  15. out_return_code OUT VARCHAR2, --存储过程返回码
  16. out_visaInfoStr OUT VARCHAR2
  17. );
  18. END PY_PCKG_REFUND2;
  19. /
  20. CREATE OR REPLACE PACKAGE BODY PY_PCKG_REFUND2 AS
  21. PROCEDURE PY_WEBREFUND_VISA_PREPARE (
  22. in_serialNoStr IN VARCHAR2, --用"|"隔开的一组网上退款申请流水号
  23. in_session_operatorid IN VARCHAR2,--业务操作员
  24. out_return_code OUT VARCHAR2, --存储过程返回码
  25. out_visaInfoStr OUT VARCHAR2
  26. ) IS
  27. --变量声明
  28. v_serialno VARCHAR2(20);--网上退款申请流水号
  29. v_refserialno VARCHAR2(20);--支付交易流水号
  30. v_tobankOrderNo VARCHAR2(30);--上送银行的订单号
  31. v_orderDate VARCHAR2(8);--订单日期
  32. v_businessType VARCHAR2(10);--业务类型
  33. v_currType VARCHAR2(3);--订单类型(ET-电子机票)
  34. v_merno VARCHAR2(15);--商户号
  35. v_orderNo VARCHAR2(20);--商户订单号
  36. v_orderState VARCHAR2(2);
  37. v_refAmount NUMBER(15,2);--退款金额
  38. v_tranType VARCHAR(2);--交易类型
  39. v_bank VARCHAR2(10);--收单银行
  40. v_date VARCHAR2 (8);--交易日期
  41. v_time VARCHAR2 (6);--交易时间
  42. v_datetime VARCHAR2 (14);--获取的系统时间
  43. v_index_start NUMBER;
  44. v_index_end NUMBER;
  45. v_i NUMBER;
  46. BEGIN
  47. -- 初始化参数
  48. out_visaInfoStr := '';
  49. v_i := 1;
  50. v_index_start := 1;
  51. v_index_end := INSTR(in_serialNoStr,'|',1,1);
  52. v_refserialno := SUBSTR(in_serialNoStr, v_index_start, v_index_end-1);
  53. v_datetime := TO_CHAR (SYSDATE, 'yyyymmddhh24miss');
  54. v_date := SUBSTR (v_datetime, 1, 8);
  55. v_time := SUBSTR (v_datetime, 9, 14);
  56. --从退款请求表中查询定单信息(商户号、商户订单号、退款金额)
  57. WHILE v_index_end > 0 LOOP
  58. SELECT
  59. WEBR_MERNO,
  60. WEBR_ORDERNO,
  61. WEBR_AMOUNT,
  62. WEBR_SERIALNO,
  63. WEBR_REFUNDTYPE
  64. INTO
  65. v_merno,
  66. v_orderNo,
  67. v_refAmount,
  68. v_serialno,
  69. v_tranType
  70. FROM
  71. PY_WEB_REFUND
  72. WHERE
  73. WEBR_REFREQNO = v_refserialno;
  74. --将查询到的数据组成串
  75. out_visaInfoStr := out_visaInfoStr || v_merno || '~' || v_orderNo || '~' || v_refAmount + '|';
  76. --为下次循环做数据准备
  77. v_i := v_i + 1;
  78. v_index_start := v_index_end + 1;
  79. v_index_end := INSTR(in_serialNoStr,'|',1,v_i);
  80. IF v_index_end > 0 THEN
  81. v_refserialno := SUBSTR(in_serialNoStr, v_index_start, v_index_end - 1);
  82. END IF;
  83. --根据原支付流水号在流水表中查询该订单的信息,包括原上送银行或第三方的订单号:WTRN_TOBANKORDERNO
  84. SELECT
  85. WTRN_TOBANKORDERNO,
  86. WTRN_ORDERNO,
  87. WTRN_ORDERDATE,
  88. WTRN_BUSINESSTYPE,
  89. WTRN_ACCPBANK,
  90. WTRN_TRANCURRTYPE
  91. INTO
  92. v_tobankOrderNo,
  93. v_orderNo,
  94. v_orderDate,
  95. v_businessType,
  96. v_bank,
  97. v_currType
  98. FROM PY_WEBPAY_VIEW
  99. WHERE WTRN_SERIALNO = v_serialno;
  100. --记录流水表(退款)
  101. INSERT INTO PY_WEBPAY_TRAN(
  102. WTRN_SERIALNO,
  103. WTRN_TRANTYPE,
  104. WTRN_ORIGSERIALNO,
  105. WTRN_ORDERNO,
  106. WTRN_ORDERDATE,
  107. WTRN_BUSINESSTYPE,
  108. WTRN_TRANCURRTYPE,
  109. WTRN_TRANAMOUNT,
  110. WTRN_ACCPBANK,
  111. WTRN_TRANSTATE,
  112. WTRN_TRANTIME,
  113. WTRN_TRANDATE,
  114. WTRN_MERNO,
  115. WTRN_TOBANKORDERNO
  116. )VALUES(
  117. v_refserialno, --和申请表的流水号相同,作为参数传人
  118. v_tranType,
  119. v_serialno, --原交易流水号,查询退款申请表得到
  120. v_orderNo,
  121. v_orderDate,
  122. v_businessType,
  123. v_currType,
  124. v_refAmount,
  125. v_bank,
  126. '1',
  127. v_time,
  128. v_date,
  129. v_merno,
  130. v_tobankOrderNo --上送银行的订单号,查询流水表得到
  131. );
  132. --更新网上退款申请表
  133. UPDATE PY_WEB_REFUND
  134. SET
  135. WEBR_IFDISPOSED = '1',
  136. WEBR_DISPOSEDOPR = in_session_operatorid,
  137. WEBR_DISPOSEDDATE = v_datetime
  138. WHERE
  139. WEBR_REFREQNO = v_refserialno;
  140. --更新定单表
  141. IF v_tranType = '2' THEN
  142. v_orderState := '7';
  143. ELSE
  144. v_orderState := '10';
  145. END IF;
  146. UPDATE PY_ORDER
  147. SET
  148. ORD_ORDERSTATE = v_orderState
  149. WHERE
  150. ORD_ORDERNO = v_orderNo
  151. AND ORD_ORDERDATE = v_orderDate
  152. AND ORD_BUSINESSTYPE = v_businessType;
  153. END LOOP;
  154. -- 异常处理
  155. EXCEPTION
  156. WHEN OTHERS THEN
  157. ROLLBACK;
  158. out_return_code := '14001';
  159. RETURN;
  160. END;
  161. END PY_PCKG_REFUND2;
  162. /

人气教程排行