存储过程入门

article/2025/8/25 13:31:14

参考文章

  1. Oracle Database concepts guide(11g2) By Thomas Kyte
  2. Stored Procedure Wiki

先修知识

  • 数据库的基本概念
  • SQL

什么是存储过程(Stored Procedure):

  • 一段存储在数据库的“子程序”,下面对这两个部分进行分开的阐释。
  • 子程序(Subprogram):
    • 一段可以被调用的子程序(subprogram)要么是一个过程(Procedrue),要么是一个函数(function).
    • 过程(Procerue)和函数(function)的区别之一是:函数总是只返回一个单个的值, 而过程并不是。(摘自Oracle Database concepts guide
    • 数据库的存储过程通常是指一系列的SQL语句构成的"SQL代码块", 和普通的SQL语句的不同点是, 代码块中包含了原生SQL所没有的元素, 例如cursor, variable,if, else, loop。
  • “存储在数据库”
    • SQL语句都是需要通过数据库相应组件编译后才能执行,最常见的例子是通过JDBC, 或ODBC创建数据区连接,发送SQL语句给数据库执行,并在程序中获得数据库返回的结果。
    • 存储过程则是把经常会被重复使用的SQL语句逻辑块封装起来,编译好,存储在数据库服务器端(这里的客户端是需要连接数据库的应用程序,但该应用程序本身也可能是一个Web服务器)。 这样,当存储过程再次被调用时,就无须编译了。 而调用的过程也无须发送SQL语句,只需要发送一个存储过程的标识, 数据库就可以找到相应的存储过程予以调用。

PL/SQL, Transact-SQL, 存储过程的概念区分

  • PL/SQL是 Oracle对SQL的扩展,Transact-SQL 是 sqlserver 对于 SQL 的扩展, 经常会与存储过程的相关文章一同出现, 容易给初学者造成存储过程即为PL/SQL 或 Transact-SQL的误解, 其实这些只是用于编写存储过程的 SQL 扩展语言。

  • 由于不同扩展 SQL 语法上存在差异,导致不同数据库的存储过程无法直接迁移。 但存储过程的概念在不同的数据库中是通用的。

存储过程的好处

  • 性能提升
    • 如之前所提到的, 原本由通过代码发送SQL实现的业务逻辑,编写封装成存储过程后, 经过编译, 存放在数据库段, 这样应用程序在调用该业务逻辑时, 就无须发送SQL语句, 也无需经历编译的步骤,从而带来性能上的提升
    • 存储过程可以利用数据库的内存共享能力, 如果一个存储过程可以被多个用户间共享,就能够节省内存的空间。
  • 开发维护的效率提升
    • 如果多个应用程序都具有通用的数据库操作逻辑,那么就可以利用数据库实现存储过程的复用,避免为每一个应用编写一套代码。 同时,如果需要修改特定业务的数据库操作逻辑, 也无须改动应用程序的代码。 另外, 存储过程可以被任意语言编写的应用程序所调用,最大限度的实现了“代码复用”。
  • 数据完整性与一致性
    • 由于存储过程可以被重复调用, 所以只要经过严格测试,并保证正确运行的存储过程,在新的代码中被使用, 也无需再次经过测试。
  • 安全性
    • 存储过程可以以定义者的权限执行,而不是使用者的权限执行。为普通用户执行敏感操作提供了一种有效的方法。
      • 举例: 假如某个应用程序要向用户提供修改密码的功能,而不同用户的用户名和密码都存储在一张User表中。
      • 如果,如果不使用存储过程, 该应用程序在访问数据库时, 必须以具有操作“User”表权限的用户身份去连接数据库。此时如果程序员编写的代码出错,或者程序员想恶意修改别人的password, 则数据库User表的安全无法保证。
      • 如果使用存储过程,则可以定义一个具有修改User表权限的存储过程changePassword(username, oldPassword, newPassword), 不具备访问 User 表的数据库用户, 依旧可以执行该存储。 而该存储过程则可实现严格的校验逻辑,即首先检查useranme, oldpassword是否匹配, 如果匹配, 则仅仅修改username所对应的password。
    • 存储过程也能以调用者的权限执行,而不是定义者的权限执行。 这使得不同权限的用户,在调用同一个存储过程时,依旧能对数据访问能力进行区分限制。
      • 举例: 一个hr_manager 用户可以运行一个 employee_update(columnName, content) 存储过程来更新员工的薪酬(salary)字段, 因为hr_manager被赋予了更新salary字段的权限。 另一个用户hr_clerk 也可以调用这一存储过程,但是他只被赋予了更新员工地址(addressBook)字段的权限,由于该存储过程被设置成了以调用者权限执行, hr_clerk如果试图更新salary列, 是无法成功的。

存储过程的缺点

  • 不易调试。
    • 如果将 sql 逻辑通过应用程序控制, 可以很方便的加断点调试, 查看各个变量的值。 如果直接编写存储过程, 则很难调试, oracle 数据库的开发工具 plsql developer 提供了一定的存储过程调试功能, 但是依旧不如应用程序的断点调试那么强大。
  • 不易迁移扩展。
    • 不同类型数据库的存储过程语法会有区别, 使用了存储过程会使得应用程序不具备迁移扩展能力。 不要问我为什么, 因为我就经历过一个在 sqlserver 有大量存储过程的应用程序迁移到 oracle 数据库的过程。

以PL/SQL为例的存储过程编写

  • PL/SQL Subprogram(子程序)的创建
CREATE PROCEDURE hire_employees 
(p_last_name VARCHAR2, p_job_id VARCHAR2, p_manager_id NUMBER, p_hire_date DATE, p_salary NUMBER, p_commission_pct NUMBER, p_department_id NUMBER)IS
BEGIN
.
INSERT INTO employees (employee_id, last_name, job_id, manager_id, hire_date, salary, commission_pct, department_id)
VALUES 
(emp_sequence.NEXTVAL, p_last_name, p_job_id, p_manager_id, p_hire_date, p_salary, p_commission_pct, p_department_id);
.
.
END;
  • PL/SQL Subprogram存储过程的执行(三种):

    • 利用oracle集成的工具,如 SQL PLUS或者 SQL Developer
    • 在数据库应用程序的代码中调用
    • 在另外一个存储过程或触发器(trigger)中调用(触发器的概念不在此文涉猎)
    • 数据库应用程序对存储过程调用场景的示意图,图片来源于参考资料1
  • PL/SQL 语言构成(Language Constructs)

    • 变量(variables)和常量(constants)
      • 可以在SQL存储过程中声明使用,和一般程序中的变量,常量的概念一致。
    • 游标(Cursor)
      • 可以在存储过程中声明使用, 主要用于实现面向数据记录(record oriented)的处理.
    • 异常(Exceptions)
      • PL/SQL允许为自定义存储过程中会抛出的异常 ,和一般程序中的异常概念类似。
  • PL/SQL运行过程:

    • PL/SQL支持两种执行方式: native execution (本地执行) 和 interpreted execution (解释执行)
      • 解释执行, PL/SQL语句集会被编译成所谓的"字节码(bytecode)"的表示方式, 类似于Java 中的bytecode, 最后会被一个oracle数据库实现的虚拟机组件解释执行
      • 本地执行, 会把PL/SQL直接编译成对应平台的object code(可以被链接成可执行程序), 由于没有解释执行的过程, 所以可以提供更好的性能。

PL/SQL执行过程,图片来源于参考资料1

  • 图中的PL/SQL engine 是用来定义,编译,执行PL/SQL语句集的组件单元。 当数据库调用存储过程时, 数据库会将经过编译的PL/SQL语句集加载到系统全局区(system global area,SGA) 共享池(shared pool)中 。 (这里不对该概念作赘述,可暂且简单理解为一片内存区域)。 然后PL/SQL engine会和语句执行器(statement executor)一同工作,来处理存储过程中的语句。

总结

存储过程思想上很简单,就是数据库SQL语言层面的代码封装与重用。 所以广义上来说, 只要是被存储在数据库,可供外部直接调用以修改数据的子程序(包括函数和过程)都可以被看做是存储过程。


http://chatgpt.dhexx.cn/article/TSlQpZTm.shtml

相关文章

【MySQL存储过程】创建一个简单的存储过程

什么是存储过程和函数 存储过程和函数是在数据库中定义的一些SQL语句的集合,然后直接调用这些存储过程和函数来执行已经定义好的SQL语句。存储过程和函数可以避免开发人员重复编写相同的SQL语句。而且,存储过程和函数是在MySQL服务器中存储和执行的&…

什么是存储过程

什么是存储过程:存储过程可以说是一个记录集吧,它是由一些T-SQL语句组成的代码块,这些T-SQL语句代码像一个方法一样实现一些功能(对单表或多表的增删改查),然后再给这个代码块取一个名字,在用到…

MySQL-存储过程

文章目录 存储过程一. 存储过程的创建和使用1. 创建存储过程2. 删除存储过程3. 查看存储过程4. 调用存储过程5. 例题 二. 变量1. 系统变量1.1 全局变量1.2 会话变量 2. 自定义变量2.1 用户变量2.2 局部变量 三. 存储过程参数3.1 说明:3.2 例题 四. 流程控制1. IF语句…

存储过程怎么使用

1.什么是存储过程? 存储过程是封装了一条或多条SQL的集合。它的好处是简单、高性能、安全。2.为什么要使用存储过程? 简化复杂的操作,把SQL封装起来容易使用。 如果所有开发人员和应用程序都使用同一存储过程,则所有使用的代码都…

SQL创建存储过程

创建SQL存储过程需要使用到的语法 - 创建存储过程 CREATE 存储过程的名称(参数) BEGIN ...需要执行的SQL语句 END- 调用 CALL 存储过程的名称(参数)个人看法,这就是一个函数...无参数 CREATE PROCEDURE p_student_select() BEGIN SELECT * FROM student; ENDCALL …

4.3.1 存储过程的简要介绍

4.3.1 存储过程的简要介绍 1、什么是存储过程? 存储过程是一种命名的PL/SQL代码块。它既可以没有参数,也可以有若干输入、输出参数,甚至可以有多个既作输入又作输出的参数,但他通常没有返回值。 存储过程被保存在数据库中&#x…

储存过程

储存过程是一组为了完成特定功能的SQL语句表,经过编译后储存在数据库中,用户通过指定过程的名字并给定参数来调用执行它。 从常用的操作数据库的SQL语句在执行的时候需要先编译,然后执行,储存过程,则是采用另外一种方式…

java笔试--北京轩宇信息

第一题 import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths;/*** <p>功能: 编写程序,在C盘根目录下创建文件myFile.txt&#xff0c;文件内容如下&#xff0c;请注意缩进和换行&#xff1a;* Java* C/C* Python* JavaScripts*/ public…

笔试——中兴

参考达尔文公众号&#xff1a;https://mp.weixin.qq.com/s?__bizMzg5MDIwNjIwMA&mid2247496018&idx1&snf8109b6f5b5ea3a175e52eb7074bb7bc&chksmcfe293c5f8951ad3570a64a07ce0deba1ec12f3c8d0a15bbf1c64ed25e5faca46ef5974fef72&mpshare1&scene23&…

中兴2016笔试题答案Java_中兴Java笔试题

中兴Java笔试题 一、选择题(每题4分,共80分) 1. 编译Java Application 源程序文件将产生相应的字节码文件&#xff0c;这些字节码文件的扩展名为( ) A. .java B. .class C. .html D. . 2. main方法是Java Application程序执行的入口点&#xff0c;关于main方法的方法头以下哪项…

中兴通讯2013校招软件笔试题

关于const的实现机制&#xff0c;请看&#xff1a; http://blog.csdn.net/syzcch/article/details/8182184 define宏定义那个题&#xff1a; http://zhidao.baidu.com/link?urltSvmJ_ytFjwWKBLzDgCfLfW-mdJtTChTab3XzBAbd2x1nGYQCGnqDq__9-dqc_ndlWE1uPeaFcyVXlKOn1CAha …

中兴笔试程序题

文本编辑器&#xff08;15&#xff09; 要求&#xff1a; &#xff08;1&#xff09;编辑文本&#xff1b; &#xff08;2&#xff09;保存、打开指定位置的文本文件&#xff1b; &#xff08;3&#xff09;具有输入输出界面。 代码&#xff1a;&#xff08;此代码在vc6.…

中兴2016校招软件在线笔试题

面试经验可以参考我的另一篇文章&#xff0c;是7月初参加openday面试的&#xff0c;文章链接http://blog.csdn.net/dandelion1314/article/details/47009585 招聘群里有人发的招聘时间安排&#xff0c;仅供参考。 据说今年是中兴的第一次在线笔试&#xff0c;摄像头监控&am…

MeasureSpec的理解和详尽源码分析

package cc.ww;import android.view.View; import android.view.View.MeasureSpec; import android.view.ViewGroup.LayoutParams; import android.view.ViewGroup.MarginLayoutParams; import android.widget.LinearLayout;/*** author http://blog.csdn.net/lfdfhl* * 文档描…

自定义View 测量过程(Measure)

目录 一、作用二、储备知识2.2 ViewGroup.LayoutParams2.3 MeasureSpec 三、measure过程详解3.1 单一View的measure过程具体流程源码分析源码总结 3.2 ViewGroup的measure过程测量原理具体流程源码分析流程总结 四、总结 一、作用 测量View的宽 / 高 在某些情况下&#xff0c;…

Android MeasureSpec解析

1. MeasureSpec组成 MeasureSpec是View的一个内部类&#xff0c;由一个32位的int值组成&#xff0c;前两位代表SpecMode测量模式&#xff0c;后30位代表SpecSize大小值。 其中测量模式共有三种&#xff1a; EXACTLY&#xff08;确定&#xff09;&#xff1a;父控件为子View指…

使用View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED)在在onCreate中获得控件的大小问题

android 在onCreate中获得控件的大小 int w View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED); int h View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED); edt_height.measure(w, h); int height edt_height.getMeasuredHeight(); int w…

MeasureSpec中三种模式:UNSPECIFIED,AT_MOST,EXACTLY

在自定义View和ViewGroup的时候&#xff0c;我们经常会遇到int型的MeasureSpec来表示一个组件的大小&#xff0c;这个变量里面不仅有组件的尺寸大小&#xff0c;还有大小的模式。 这个大小的模式&#xff0c;有点难以理解。在系统中组件的大小模式有三种&#xff1a; 1.精确模式…

评测指标(metrics)

评测指标(metrics) metric主要用来评测机器学习模型的好坏程度,不同的任务应该选择不同的评价指标, 分类,回归和排序问题应该选择不同的评价函数. 不同的问题应该不同对待,即使都是 分类问题也不应该唯评价函数论,不同问题不同分析. 回归(Regression) 均方误差(MSE) (1) l ( y…

MeasureSpec学习—对Integer.MAX_VALUE 2的认识

在自定义View和ViewGroup的时候&#xff0c;我们经常会遇到int型的 MeasureSpec 来表示一个组件的大小&#xff0c;这个变量里面不仅有组件的尺寸大小&#xff0c;还有大小的模式。 这个大小的模式&#xff0c;有点难以理解。在系统中组件的大小模式有三种&#xff1a; 1.精确…