PL/SQL Step By Step(三)

1.什么是存储过程    

    这篇博客主要介绍存储过程(Stored Procedure),简称过程。存储过程是Oracle PL/SQL中的一种程序单元。存储过程可以通过给一个PL/SQL语句块命名从而将这个语句块存储在数据库中,以便将来可以被反复的调用。

    存储过程与一般的匿名PL/SQL块的一个主要区别是有无确定的名称。此外,对于匿名块来说,每次提到到数据库进行执行时,PL/SQL解析程序都会对其 进行一次解析,然后再运行;然而对于存储过程来说,PL/SQL的解析程序只在其创建时对其进行一次解析,后续的调用就不需要再次解析了。

    存储过程可以在其他耳朵可执行语句中被调用,比如说另外一个匿名块或者另一个存储过程等,并且,存储工程还可以带参数。下面我们先看一段存储过程的示例代码:

PROCEDURE PROC_UPDATE_CRUISE_STATUS IS
  v_today DATE
BEGIN
  SELECT TRUNC(SYSDATE)
  INTO v_today
  FROM DUAL;
  
  UPDATE CRUISES
    SET STATUS = 'DISABLED'
  WHERE TRUNC(START_DATE) < v_today
    AND TRUNC(END_DATE) < v_today
    AND STATUS <> 'CANCELED';
    
  UPDATE CRUISES
    SET STATUS = 'COMPLETE';
  WHERE TRUNC(END_DATE) < v_today
    AND STATUS <> 'CANCELED';
    
  COMMIT;
END;
/

    这段代码会根据表CRUISES中的START_DATE和END_DATE与当前系统时间的关系来更新CRUISES表。对于这个存储过程来说,它是没有一个明确的返回值的,但是,执行该存储过程之后,整个数据库都能体现出表中每一行数据的更新后的状态了。

    还有一点需要特别的指出来。当你给别的用户赋予执行某个存储过程的权限的时候,即使这个用户对于存储过程所操作的表的访问权限,该用户也是可以执行存储过 程的,这一点与普通的PL/SQL块也是不一样的。存储过程存放最多的位置还是数据库中,这种情况下,任何能够访问该数据库并且具有执行这个存储过程权限 的应用程序均可以调用它。除此之外,存储过程也可以存在于客户端应用程序中,比如说基于Oracle Form Builder构建的程序,但是,这样的程序中的存储过程是不能被网络上的其他用户调用的。

2.创建、更改、删除存储过程

    创建一个存储过程可以采用CREATE PROCEDURE proc_name语句。完整的语法可以参考Oracle的官方文档,我这里只贴一张截图:

    光看这个图会有一种一下被shock到的感觉。其实实际中咱们写的存储过程不太可能完整的用到上面的语法图表示的内容。因此,我们这里只讲解最主要的部分。先说创建存储过程,还是看例子吧:

CREATE OR REPLACE PROCEDURE proc_clear_log IS
BEGIN
  DELETE FROM ERRORS;
  COMMIT;
END;
/

    这是一个再简单不过的创建存储过程的例子,其它部分和前面讲到的块没什么区别,只是需要遵守格式的要求:上面的例子中OR REPLACE是可选的,意思就是字面的意思:当这个存储过程名称已经有了就把原来的替换掉。关键字IS也可以用AS代替,当然会有不同,我们后面讲到再 说。我们第一个例子还不涉及到带参数的存储过程,参数部分我们接下来会专门讲。

    当提交一个CREATE PROCEDURE命令到数据库(比如说利用SQL*PLUS),会发生下面的过程:

  • 代码被存储在数据字典中
  • 代码语法解析,并且最终被判定为VALID或者INVALID
  • 如果是VALID,那么数据库会返回"Procedure created"提示信息,并且该存储过程随时可以被调用        
  • 如果是INVALID,那么数据库会返回相应的错误信息,比如说类似于ORA-12222的错误号,该存储过程不能被调用    

    需要注意的是,无论解析与否,通过与否,存储过程的代码都会保存在数据字典中。作为一个好的习惯来说,你还可以给存储过程的END加上标签,也就是过程的名称,如下:

CREATE OR REPLACE PROCEDURE proc_clear_log IS
BEGIN
  DELETE FROM ERRORS;
  COMMIT;
END proc_clear_log;

    下面我们再说说修改存储过程,修改存储过程会有两种情况,因此也有两种不同的对应方法。如果说你的处理逻辑需要变化,换句话说,存储过程本身需要调整,那 么可以采用上文提到的OR REPLACE选项来完整的替换掉之前的那个存储过程。第二种情况是,当存储过程内部所引用的数据库对象发生了变化,这时,数据库会强制将引用该对象的存 储过程设置为INVALID状态。这时需要使用ALTER PROCEDURE语法。这句话可能不好理解,我们举例说明:

    对于上面的例子,存储过程proc_clear_log使用到了一个表ERRORS,现在假设我们修改表的结构如下:

ALTER TABLE ERRORS ADD ERROR_SOURCE VARCHAR2(30);

    这时,数据库会自动将proc_clear_log标记为INVALID,也就不能被执行了。但是我们知道表的更改实际上不影响存储过程proc_clear_log正确运行,那么要使存储过程重新变回VALID状态,可以使用下面的语句:

 

ALTER PROCEDURE proc_clear_log COMPILE;

    这个语句会重新触发Orale PL/SQL的解析程序去重新编译存储过程proc_clear_log,如果确实表的更改实际上不会影响proc_clear_log,那么,它会将proc_clear_log状态设置回VALID。

    删除存储过程就非常简单,相信读者大概都猜到了:

DROP PROCEDURE proc_clear_log;

3.如何调用存储过程?

    调用存储过程有两种方法:在PL/SQL块中调用和使用SQL*PLUS命令调用。下面先讲讲第一种方法:

    可以在任何一个PL/SQL块中的执行语句中调用已有的存储过程。直接用存储过程的名称即可调用。直接看代码:

BEGIN
    proc_clear_log;
END;

    这样的一个匿名块中可以调用多个不同的存储过程,并且可以和普通的SQL语句混合使用。上面这个匿名代码块本身就可以定义为一个存储过程。换句话说,存储过程中也是可以调用其他存储过程的。

    另一种调用存储过程的办法是在SQL*PLUS中使用其特有的命令来执行:

--下面的两种是一样的
EXECUTE proc_clear_log;
EXEC proc_clear_log;

4.存储过程参数

    存储过程的参数定义在存储过程顶部,集中在一对小括号中。每一个参数的定义都包括以下几个方面:

  • 参数名    
  • 参数的类型,IN或者OUT或者IN OUT类型。默认是IN类型    
  • 数据类型:只能给出类型,不能给出精度、长短等。比如你可以定义类型为varchar2,但是不能定义为varchar2(30)  
  • 默认值(可选):通过使用DEFAULT关键字给某个参数指定默认值。

    此外,参数之间使用逗号隔开。下面我们看一个带有参数的存储过程的定义:

CREATE OR REPLACE PROCEDURE proc_example( 
       p_start_date IN DATE DEFAULT SYSDATE
      ,p_days       IN NUMBER
      ,p_name       IN VARCHAR2 DEFAULT 'TOM'
)
IS
......

    参数可以接受任何PL/SQL变量能接受的类型。但是不允许提供长度、精度信息。此外,参数类型可以接受%TYPE。参数可以提供默认值,这一点是可选 的。但是只能给IN类型的参数提供默认值。除了上面的提供默认值的方法,还可以不写DEFAULT,而通过:=来提供默认值。

    对于提供了默认值的存储过程参数来说,在调用的时候可以不提供这些参数的值,而只提供没有默认值的参数提供值。但是,如果最后面的参数有默认值,而前面的 参数没有,那还好说,后面的参数不提供值就好。但是如果反过来呢,这就有点麻烦。我们后面会讲解决这个问题的办法。

5.参数类型

    有必要单独把参数类型IN、OUT、IN OUT单独列出来说一下。

  • IN类型

    IN类型的参数必须由调用者为其提供参数值,当然,如果定义了默认值给不给参数值都可以。一旦给了参数值,并且存储过程开始运行,那么,该该参数的值就不可以改变,换句话说,IN参数是只读的。

    除此之外,在定义参数的时候,如果是IN类型,可以不写。因为IN是默认的参数类型。上面的那个例子就可以写成:

CREATE OR REPLACE PROCEDURE proc_example( 
       p_start_date DATE DEFAULT SYSDATE
      ,p_days       NUMBER
      ,p_name       VARCHAR2 DEFAULT 'TOM'
)
IS
......

    我们看一个完整的定义和调用的例子:

--定义开始
PROCEDURE PROC_SHECULE_CRUISE(
          p_start_date IN DATE DEFAULT SYSDATE,
          p_days       IN NUMBER,
          p_ship_id    IN NUMBER,
          p_cruise_id  IN VARCHAR2
)
IS
  v_cruise_type_id CRUISE_TYPES.CRUISE_TYPE_ID%TYPE
BEGIN
  ...
END;
--定义结束

--调用开始
DECLARE
  v_ship_id NUMBER(4):=1;
BEGIN 
  PROC_SHECULE_CRUISE('04-JAN-2012',3,v_ship_id,'Alex');
END;
/
--调用结束
  • OUT类型

    OUT类型参数与IN类型参数则刚好相反,OUT类型的参数是不允许调用者向其提供参数值的。并且OUT类型的参数是不允许提供默认值的。除此之 外,OUT类型的参数的值最终会被返回给调用者。正是因此,在涉及到OUT类型参数的存储过程的调用就不一样了。毕竟,OUT类型的参数是需要传递回调用 者的,那么调用者必须有相应的参数来接受返回的OUT参数。我们看一个例子:

--定义开始
PROCEDURE PROC_GET_EMPLOYEE_INFO(
          p_employee_id   IN   NUMBER,
          p_first_name    OUT  VARCHAR2;
          p_last_name     OUT  VARCHAR2  
)
IS
BEGIN
  SELECT FIRST_NAME,LAST_NAME
  INTO p_first_name,p_last_name
  FROM EMPLOYEES
  WHERE EMPLOYEE_ID=p_employee_id
END;
/
--定义结束

--调用开始
DECLARE
  v_first_name VARCHAR2(30),
  v_last_name VARCHAR2(30),
BEGIN
  PROC_GET_EMPLOYEE_INFO(15,v_first_name,v_last_name);
  • IN OUT参数

    有的参数可以既具备IN类型参数的特点,又具备OUT类型参数的特点。也就是说,既可以被调用者传递值进来,执行完存储过程,修改了值之后再将参数值传递给调用者。但是IN OUT类型参数不允许定义默认值。

6.参数传递方式

    我们之前所有涉及到的参数传递,都是按照参数传递的顺序一个一个的指定参数的值。但是这种方法会遇到问题,我们在上面也讲到。假设定义四个参数,第一个给了默认值,第二个没给,第三个第四个都给了参数值。该怎么调用呢?

    可以使用一个新的操作符=>通过名称指定给第几个参数赋值,代码如下:

PROC_INVOKE(p_second=>20);

    以上基本上就是我认为的存储过程的主要内容,欢迎补充交流。

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在现有省、市港口信息化系统进行有效整合基础上,借鉴新 一代的感知-传输-应用技术体系,实现对码头、船舶、货物、重 大危险源、危险货物装卸过程、航管航运等管理要素的全面感知、 有效传输和按需定制服务,为行政管理人员和相关单位及人员提 供高效的管理辅助,并为公众提供便捷、实时的水运信息服务。 建立信息整合、交换和共享机制,建立健全信息化管理支撑 体系,以及相关标准规范和安全保障体系;按照“绿色循环低碳” 交通的要求,搭建高效、弹性、高可扩展性的基于虚拟技术的信 息基础设施,支撑信息平台低成本运行,实现电子政务建设和服务模式的转变。 实现以感知港口、感知船舶、感知货物为手段,以港航智能 分析、科学决策、高效服务为目的和核心理念,构建“智慧港口”的发展体系。 结合“智慧港口”相关业务工作特点及信息化现状的实际情况,本项目具体建设目标为: 一张图(即GIS 地理信息服务平台) 在建设岸线、港口、港区、码头、泊位等港口主要基础资源图层上,建设GIS 地理信息服务平台,在此基础上依次接入和叠加规划建设、经营、安全、航管等相关业务应用专题数据,并叠 加动态数据,如 AIS/GPS/移动平台数据,逐步建成航运管理处 "一张图"。系统支持扩展框架,方便未来更多应用资源的逐步整合。 现场执法监管系统 基于港口(航管)执法基地建设规划,依托统一的执法区域 管理和数字化监控平台,通过加强对辖区内的监控,结合移动平 台,形成完整的多维路径和信息追踪,真正做到问题能发现、事态能控制、突发问题能解决。 运行监测和辅助决策系统 对区域港口与航运业务日常所需填报及监测的数据经过科 学归纳及分析,采用统一平台,消除重复的填报数据,进行企业 输入和自动录入,并进行系统智能判断,避免填入错误的数据, 输入的数据经过智能组合,自动生成各业务部门所需的数据报 表,包括字段、格式,都可以根据需要进行定制,同时满足扩展 性需要,当有新的业务监测数据表需要产生时,系统将分析新的 需求,将所需字段融合进入日常监测和决策辅助平台的统一平台中,并生成新的所需业务数据监测及决策表。 综合指挥调度系统 建设以港航应急指挥中心为枢纽,以各级管理部门和经营港 口企业为节点,快速调度、信息共享的通信网络,满足应急处置中所需要的信息采集、指挥调度和过程监控等通信保障任务。 设计思路 根据项目的建设目标和“智慧港口”信息化平台的总体框架、 设计思路、建设内容及保障措施,围绕业务协同、信息共享,充 分考虑各航运(港政)管理处内部管理的需求,平台采用“全面 整合、重点补充、突出共享、逐步完善”策略,加强重点区域或 运输通道交通基础设施、运载装备、运行环境的监测监控,完善 运行协调、应急处置通信手段,促进跨区域、跨部门信息共享和业务协同。 以“统筹协调、综合监管”为目标,以提供综合、动态、实 时、准确、实用的安全畅通和应急数据共享为核心,围绕“保畅通、抓安全、促应急"等实际需求来建设智慧港口信息化平台。 系统充分整合和利用航运管理处现有相关信息资源,以地理 信息技术、网络视频技术、互联网技术、移动通信技术、云计算 技术为支撑,结合航运管理处专网与行业数据交换平台,构建航 运管理处与各部门之间智慧、畅通、安全、高效、绿色低碳的智 慧港口信息化平台。 系统充分考虑航运管理处安全法规及安全职责今后的变化 与发展趋势,应用目前主流的、成熟的应用技术,内联外引,优势互补,使系统建设具备良好的开放性、扩展性、可维护性。
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值