创建/更新存储过程

基础基础用法

创建/修改无参存储过程

CREATE OR REPLACE PROCEDURE procedure_name [IS|AS]
--声明全局变量(可选)
BEGIN
--存储过程的执行体
END; --也可以写成 END procedure_name;

创建/修改携参数存储过程

CREATE OR REPLACE PROCEDURE procedure_name(var_name1 IN type, var_name2 IN type,...,var_nameN OUT type) [IS|AS]
--声明全局变量(可选)
BEGIN
--存储过程的执行体
END; --也可以写成 END procedure_name;

说明:IN 表示输入参数,OUT表示输出参数,比如存储返回值的变量,IN OUT 表示输入输出参数(注:都不区分大小写)

注意:

  1. 存储过程参数数据类型不能指定长度
  2. OUT、IN OUT 模式参数的调用,必须通过变量实现

调用存储过程

--调用带参数存储过程
CALL procedure_name([参数列表]);
--或者
BEGIN procedure_name(参数列表); END; --注意 分号不能少,特别是END后面的分号
--或者
SQL> EXEC procedure_name(参数列表); --在命令行窗口执行,比如SQLPlus执行窗口 --调用不带参数存储过程
CALL procedure_name();
--或者
BEGIN procedure_name; END; --注意 分号不能少,特别是END后面的分号
--或者
BEGIN procedure_name(); END; --注意 分号不能少,特别是END后面的分号
--或者
SQL> EXEC procedure_name;

简单的示例

创建携带参数存储过程

CREATE OR REPLACE PROCEDURE SP_TEST_PROC(workDate IN Date) is
BEGIN
dbms_output.put_line('The input date is:'||to_date(workDate,'yyyy-mm-dd'));
END; CALL SP_TEST_PROC(sysdate); --输出:The input date is:22-AUG-24 --创建携带返回值存储过程
CREATE OR REPLACE PROCEDURE SP_SUM_PROC(number1 IN NUMBER, number2 IN NUMBER, result OUT NUMBER) is
BEGIN
result := number1 + number2;
END; -- sql窗口中调用
DECLARE res NUMBER(6);
BEGIN
SP_SUM_PROC(1, 3, res);
dbms_output.put_line(res); --输出:4
END; -- 命令行窗口中调用
SQL> VARIABLE res NUMBER;
SQL> EXEC SP_SUM_PROC(1, 3, :res);
PL/SQL procedure successfully completed
res
---------
4 --创建带输入输出参数的存储过程
CREATE OR REPLACE PROCEDURE SP_SUM_PROC(number1 IN NUMBER, number2 IN OUT NUMBER) is
BEGIN
number2 := number1 + number2;
END; -- 调用
DECLARE num NUMBER(6) :=3; --注意,不能在存储过程中声明变量时这样赋值
BEGIN
dbms_output.put_line('调用前num变量值:' || num); --输出:调用前num变量值:3
SP_SUM_PROC(1, num);
dbms_output.put_line('调用后num变量值:' || num); --输出:调用后num变量值:4
END;

DECLARE基础用法说明

可以在BEGIN关键字之前,使用DECLARE定义、声明局部变量,声明基础用法如下:

DECLARE 变量名[,变量名2...] 数据类型(含长度、精度) [DEFAULT value]; --没有使用DEFAULT子句时,默认值为NULL

示例:

DECLARE num INT  DEFAULT 10; --声明变量 num,数据类型为INT型,默认值为10
DECLARE usrname VARCHAR2(15) DEFAULT 'tester'; --声明变量 username,默认值为tester
DECLARE age, num int; -- 定义多个变量
DECLARE length, width NUMBER(18,2) DEFAULT 10; -- 声明变量 length, width,默认值都为10
BEGIN
-- do something
END;

创建无参数存储过程

CREATE OR REPLACE PROCEDURE SP_TEST_PROC is
BEGIN
dbms_output.put_line('hello, tester');
END; --调用
CALL SP_TEST_PROC(); --输出:hello, tester
--或者
BEGIN
SP_TEST_PROC;
END;

声明全局变量

方式一:直接声明数据类型

格式:变量名 数据类型(大小及精度)

示例:

v_username VARCHAR2(15);
v_num NUMBER(9,2);

方式二:使用%TYPE声明

格式:变量名 表名.字段名%TYPE

含义:该变量的数据类型与指定表的指定字段的数据类型一致

示例:

r_carrierID  CARRIERS.carrier_id%type;

方式三:使用%ROWTYPE声明

格式:变量名 表名%ROWTYPE

含义:该变量的数据类型与指定表的指定行记录(所有字段)的数据类型一致

示例:

V_row_user USERS%ROWTYPE; --V_row_user存放整行数据

注:不管使用哪种声明方式,变量名都不区分大小写,以字母开头;此外,变量的声明必须在BEGIN关键字之前进行。

变量赋值

方式一:使用":="直接赋值

注意,这种方式不适合使用%ROWTYPE声明的变量

示例:

v_username := 'shouke';

我们可以在声明变量的同时对变量进行赋值。

v_username VARCHAR2(15) := 'shouke'

方式二:select 表字段 into 变量 from 表

1:查询指定表的某些指定字段  

不适合使用%ROWTYPE声明的变量

SELECT field1,field2,...,field3 INTO varName1,varName2,...,varNameN FROM tableName;

2:查询指定表的所有字段  

SELECT * INTO v_row_varName FROM tableName; --其中v_row_varName为使用%ROWTYPE声明的变量

注意:使用这种方式给使用%ROWTYPE声明的变量赋值时,查询结果只能返回一条记录,且查询结果必须包含该表的所有字段。

变量声明与赋值示例

示例

CREATE OR REPLACE PROCEDURE SP_TEST_PROC IS
v_username VARCHAR2(15);
v_companyCode NUMBER(9,2);
v_erpOrderNo EFFECTIVE_OMS_MSG_FOR_TEST.erp_Orderno%TYPE;
v_record EFFECTIVE_OMS_MSG_FOR_TEST%ROWTYPE;
BEGIN
v_username := 'shouke';
SELECT request_msg_id INTO v_companyCode FROM EFFECTIVE_MSG_FOR_TEST WHERE rownum <2;
SELECT erp_orderno INTO v_erpOrderNo FROM EFFECTIVE_MSG_FOR_TEST WHERE rownum <2;
SELECT * INTO v_record FROM EFFECTIVE_MSG_FOR_TEST WHERE rownum <2; dbms_output.put_line('v_username: ' || v_username);
dbms_output.put_line('v_companyCode: ' || v_companyCode);
dbms_output.put_line('v_erpOrderNo: ' || v_erpOrderNo);
dbms_output.put_line('v_record.company_code: ' || v_record.company_code); END; call SP_TEST_PROC();

注意:

  • 采用变量名.表字段名的方式来引用通过%ROWTYPE声明的变量
  • 不能直接使用变量名作为查询列,错误用法形如 SELECT v_erpOrderNo FROM EFFECTIVE_MSG_FOR_TEST;

一个应用实例

--创建序列
CREATE SEQUENCE check_orders_seq
increment By 1
start With 1
Maxvalue 2000
Minvalue 1
cycle
Nocache; --创建存储过程
CREATE OR REPLACE PROCEDURE "SP_GET_CHECK_ORDERS_FOR_TEST" (IN_serverID IN VARCHAR2, IN_rowLimit IN INT, OUT_returnCode OUT VARCHAR2)
IS
sqlStr VARCHAR2(5000);
BEGIN
OUT_returnCode := '000'; --将拣货完成未复核,且未在临时表check_orders_for_test的订单拉入临时表
sqlStr := 'insert into check_orders_for_test(warehouseID, orderNo, rangeNo, checkFlag, serverID) select h.warehouseID, h.orderNo, check_orders_seq.nextval rangeNo, ''N'' checkFlag,'''||IN_serverID||''' serverID
from doc_order_header h
where h.sostatus = ''60''
and exists (select 1 from act_allocation_details a
where a.orderNo = h.orderNo
and a.packflag = ''N'')
and not exists (select 1 from check_orders_for_test m
where m.orderno = h.orderno)
and rownum <= '||IN_rowLimit;
execute immediate sqlStr;
commit;
Return;
EXCEPTION
WHEN OTHERS THEN
OUT_returnCode := 'SP_GET_CHECK_ORDERS_FOR_TEST' || SQLerrm;
dbms_output.put_line(OUT_returnCode);
ROLLBACK;
END;

说明:两个''表示一个'

执行体之逻辑判断语句

IF语句

基础用法

IF 条件表达式 THEN
-- do something
END IF;
IF 条件表达式 THEN
-- do something
ELSE
-- do something
END IF;
IF 条件表达式 THEN
-- do something
ELSIF 条件表达式 THEN
-- do something
... --表省略,支持更多的ELSIF
ELSE --子句可选
-- do something
END IF;

示例

CREATE OR REPLACE PROCEDURE SP_TEST_PROC(num IN NUMBER) IS
BEGIN
--如果num为1,则输出true
IF num=1 THEN
BEGIN
dbms_output.put_line('true');
END;
END IF;
END; CALL SP_TEST_PROC(1);

CREATE OR REPLACE PROCEDURE SP_TEST_PROC(num IN NUMBER) IS
BEGIN
IF NUM=1 THEN --如果num为1,则输出 true
dbms_output.put_line('true');
ELSE --否则输出 false
dbms_output.put_line('false');
END IF;
END;

CREATE OR REPLACE PROCEDURE SP_TEST_PROC(num IN NUMBER) IS
BEGIN
IF NUM=1 THEN --如果num为1,则输出 true
dbms_output.put_line('true');
ELSIF NUM=0 THEN --否则,如果num为2,则输出 false
dbms_output.put_line('false');
ELSE --否则输出 invalid num
dbms_output.put_line('invalid num');
END IF;
END;

CASE WHEN语句

基础用法

CASE
WHEN num=1 THEN
--do something
WHEN num=2 THEN
--do something
... --表省略,支持更多的WHEN
ELSE
--do something
END CASE;

示例

CREATE OR REPLACE PROCEDURE SP_TEST_PROC(num IN NUMBER) IS
BEGIN
CASE
WHEN num=1 THEN --如果num为1,则输出 true
dbms_output.put_line('true');
WHEN num=2 THEN --如果num为1,则输出 false
dbms_output.put_line('false');
ELSE --否则输出 invalid num
dbms_output.put_line('invalid num');
END CASE;
END;

执行体之循环遍历语句

FOR循环

基础用法

FOR var IN range LOOP
--do something
END LOOP; --遍历查询结果集
FOR row IN (查询语句) LOOP
--do something
END LOOP; --循环遍历数组 --循环遍历游标(使用示例参见下文 执行体之游标)

示例

CREATE OR REPLACE PROCEDURE SP_TEST_PROC IS
BEGIN
-- FOR i IN REVERSE 0..5 LOOP --REVERSE 采用逆序,从大到小,i取值从5到0
FOR i IN 0..5 LOOP -- i取值从0到5
dbms_output.put_line('运行第' || i || '次');
END LOOP;
END; CALL SP_TEST_PROC();

运行输出:

运行第0次
运行第1次
运行第2次
运行第3次
运行第4次
运行第5次

遍历查询结果集

CREATE OR REPLACE PROCEDURE SP_TEST_PROC IS
BEGIN
FOR cur_row IN (SELECT request_msg_id, erp_orderno FROM effective_oms_msg_for_test WHERE ROWNUM<5)
LOOP
dbms_output.put_line('msg_id: ' || cur_row.request_msg_id || ' orderno: ' || cur_row.erp_orderno);
END LOOP;
END; CALL SP_TEST_PROC();

WHILE循环

基础用法

WHILE 条件语句 LOOP
-- do something
END LOOP;

示例

CREATE OR REPLACE PROCEDURE SP_TEST_PROC IS
i INT :=1 ;
BEGIN
WHILE i < 3 LOOP
dbms_output.put_line('运行第' || i || '次');
i := i + 1;
END LOOP;
END; CALL SP_TEST_PROC();

调用输出

运行第1次
运行第2次

LOOP循环

基础用法

LOOP
--do something
IF 退出循环条件 THEN
--do something
EXIT;
END IF;
--do something
END LOOP;
LOOP
--do something
EXIT WHEN 退出循环条件;
--do something
END LOOP;

示例

CREATE OR REPLACE PROCEDURE SP_TEST_PROC IS
i INT :=1;
BEGIN
LOOP
IF i=3 THEN --如果i=3,则退出
EXIT;
END IF;
dbms_output.put_line('运行第' || i || '次');
i := i + 1;
END LOOP;
END;
CREATE OR REPLACE PROCEDURE SP_TEST_PROC IS
i INT :=1;
BEGIN
LOOP
EXIT WHEN i = 3;
dbms_output.put_line('运行第' || i || '次');
i := i + 1;
END LOOP;
END;

调用结果,同上述WHILE循环示例

执行体之GOTO跳转语句

基础用法

<<gotoLabel>>
-- do something
GOTO gotoLabel;

示例

CREATE OR REPLACE PROCEDURE SP_TEST_PROC IS
i int := 1;
BEGIN
<<loop_lable>>
dbms_output.put_line('运行第' || i || '次');
i := i + 1;
IF i < 3 THEN
GOTO loop_lable;
END IF;
END;

调用结果,同上述WHILE循环示例

说明:如上,我们也可以利用GOTO语句来实现循环

执行体之游标

基础用法

CURSOR型游标

CREATE OR REPLACE PROCEDURE SP_TEST_PROC IS
CURSOR cursor_name IS 查询语句; -- 定义CURSOR类型游标(不能用于参数传递)
BEGIN
FOR varName IN cursor_name LOOP
--do something --引用变量 varName.field
END LOOP;
END;

注意:通过以上方式,采用FOR循环遍历游标,会自动关闭游标,不需要在END LOOP; 后添加关闭游标的代码CLOSE cursor_name;,会报错

示例

CREATE OR REPLACE PROCEDURE SP_TEST_PROC IS
CURSOR cursor_for_msgs IS SELECT request_msg_id, erp_orderno FROM effective_msg_for_test WHERE ROWNUM<5;
BEGIN
FOR msg IN cursor_for_msgs LOOP
dbms_output.put_line('msg_id: ' || msg.request_msg_id || ' orderno: ' || msg.erp_orderno);
END LOOP;
END;

SYS_REFCURSOR型游标

SYS_REFCURSOR型游标,该游标是Oracle以预先定义的游标,可作出参数进行传递

基础用法

CREATE OR REPLACE PROCEDURE SP_TEST_PROC IS
v_cursor_name SYS_REFCURSOR ;
--变量定义
BEGIN
OPEN v_cursor_name FOR 查询语句;
LOOP
FETCH v_cursor_name INTO 变量1, 变量2, ..., 变量N; --变量个数和查询结果记录包含的字段数量保持一致
EXIT WHEN v_cursor_name%NOTFOUND;
END LOOP;
CLOSE v_cursor_name;
END;

说明: SYS_REFCURSOR中可使用三个状态属性:

  • %NOTFOUND 表示未找到记录信息
  • %FOUND 表示找到记录信息
  • %ROWCOUNT 表示当前游标所指向的行位置
  • %ISOPEN 如果游标已经打开,则返回TRUE,否则返回FALSE

注意:

  • SYS_REFCURSOR游标只能通过OPEN方法来打开和赋值

  • SYS_REFCURSOR游标只能通过FETCH INTO方法来遍历取值

示例

CREATE OR REPLACE PROCEDURE SP_TEST_PROC IS
v_cursor_for_msgs SYS_REFCURSOR ;
v_request_msg_id VARCHAR2(20);
v_erp_orderno VARCHAR2(50);
BEGIN
OPEN v_cursor_for_msgs FOR SELECT request_msg_id, erp_orderno FROM effective_msg_for_test WHERE ROWNUM<5;
LOOP
FETCH v_cursor_for_msgs INTO v_request_msg_id, v_erp_orderno;
EXIT WHEN v_cursor_for_msgs%NOTFOUND;
dbms_output.put_line('msg_id: ' || v_request_msg_id || ' orderno: ' || v_erp_orderno);
END LOOP;
-- 注意,上述循环执行完成后,Orable并没有自动关闭游标,需要显示关闭游标
IF v_cursor_for_msgs%ISOPEN THEN
dbms_output.put_line('CLOSING CURSOR');
CLOSE v_cursor_for_msgs;
END IF;
END;

显示关闭游标

CLOSE cursor_name;

删除存储过程

基础语法

DROP PROCEDURE procedure_name;

Oracle 存储过程学习总结的更多相关文章

  1. Oracle存储过程学习使用

    存储过程创建语法: create or replace procedure 存储过程名(param1 in type,param2 out type) as 变量1 类型(值范围); 变量2 类型(值 ...

  2. ORACLE存储过程学习

    存储过程 1 CREATE OR REPLACE PROCEDURE 存储过程名 2 IS 3 BEGIN 4 NULL; 5 END; 行1: CREATE OR REPLACE PROCEDURE ...

  3. Oracle 存储过程学习

    转自:http://blog.chinaunix.net/uid-20495387-id-174394.html http://www.cnblogs.com/rootq/articles/11000 ...

  4. Oracle存储过程学习备忘

    之前的项目使用存储过程很少,但在实际的项目中,存储过程的使用是必不可少的. 存储过程是一组为了完成特定功能的SQL 语句 集,经编译后存储在数据库中:存储过程创建后,一次编译在程序中可以多次调用,对安 ...

  5. Oracle 存储过程学习笔记

    1.存储过程简单实例 CREATE OR REPLACE PROCEDURE 存储过程名称 (参数in,参数out) AS -- 变量声明,每个声明用分号结束.可以在声明的同时初始化 name ); ...

  6. Oracle存储过程学习笔记

    SQL是一种语言! SQL是一种语言! SQL是一种语言! 个人理解:存储过程就相当于Java中的方法;声明变量区域就相当于java中的声明局部变量一样,只是放到一个指定区域定义了 一.先看一部分基础 ...

  7. oracle 存储过程学习感悟

    1.跟大白话差不多 2.if...then.... else ....写的比较多 3.调用存储过程命令:execute procedure_name 4.调用存储函数命令:select '0' str ...

  8. oracle存储过程学习---包的概念

    转自:http://www.iteye.com/topic/1111793 一.包的概念   类似于一个容器,能打包相应的Pl/SQL变量.常量.函数.过程.复合数据类型等元素到这个容器内.用来限制  ...

  9. 用java调用oracle存储过程总结(转)

    //1.call+包名+存储过程名(传入.传出值用?) String str="{call SMSBUSINESS.deleteZhZMember(?,?,?)}"; //2.建立 ...

  10. oracle 存储过程 动态sql语句

    一.在oracle项目开发中越到问题: 在利用ODP向oracle中插入数据时,如果这样写:   insert into clobTable (id, story) values(1,'....'); ...

随机推荐

  1. 【Sqlserver】查看所有数据库的大小 创建日期 名称 版本级别 状态

    EXEC  sp_helpdb

  2. 一个IDEA界面如何同时打开多个项目

    第一步:先导入其中一个工程 第二步:点击File->Project Structure 第三步:导入模块 最后点击Apply即可完成一个IDEA界面同时打开多个项目的需求.

  3. jsonp原理详解——终于弄明白了JSONP

    什么是JSONP? 其实网上关于JSONP的讲解有很多,但却千篇一律,而且云里雾里,对于很多刚接触的人来讲理解起来有些困难,着用自己的方式来阐释一下这个问题,看看是否有帮助. 1.一个众所周知的问题, ...

  4. statefulset有状态应用管理

    statefulset介绍 StatefulSet(有状态集,缩写为sts)常用于部署有状态的且需要有序启动的应用程序,比如在进行SpringCloud项目容器化时,Eureka的部署是比较适合用St ...

  5. CF1838A-Blackboard-List

    题意简述 在黑板上有两个数字,进行如下操作 \(n-2\) 次: 每次在黑板上选择任意两个数,将两个数的差的绝对值写在黑板上. 这样你会得到一个长度为 \(n (3 \le n \le 100)\) ...

  6. ABC332

    D 我们可以把矩阵 \(\text{A}\) 看成 \({p,q}\). \(p\) 指现在一行最开始在哪里,\(q\) 指现在这一列最开始在哪里. 于是我们枚举 \(p\) 和 \(q\) 所有可能 ...

  7. Easysearch 跨集群复制实战

    在之前的文章中,有通过网关实现容灾的案例.今天给大家介绍 Easysearch 的跨集群复制功能.该功能可在集群之间复制数据,应用场景包括但不限于以下举例: 灾备同步:将数据同步到灾备中心,灾备中心可 ...

  8. Thread的join方法demo

    Thread的join方法demo /** * 关于join官方的解释是 Waits for this thread to die. 也就是等待一个线程结束. */ public class Thre ...

  9. 安装Ingress-Nginx

    目前,DHorse(https://gitee.com/i512team/dhorse)只支持Ingress-nginx的Ingress实现,下面介绍Ingress-nginx的安装过程. 下载安装文 ...

  10. python selenium UI自动化操作iframe及返回默认页面

    页面操作的场景:进到到页面A,选择页面A里面的记录,点击签约, 弹出一个弹窗B,弹窗B的内容是协议及同意按钮或其他非同意的提示信息,主要的操作,打开页面A,点击签约,点击同意,操作完成 分析页面的组成 ...