当前位置: 首页 > news >正文

SQL使用存储过程

本文介绍什么是存储过程,为什么要使用存储过程,如何使用存储过程,以及创建和使用存储过程的基本语法。

1. 存储过程

迄今为止,我们使用的大多数SQL语句都是针对一个或多个表的单条语句。并非所有操作都这么简单,经常会有一些复杂的操作需要多条语句才能完成,例如以下的情形:

  • 为了处理订单,必须核对以保证库存中有相应的物品。

  • 如果物品有库存,需要预定,不再出售给别的人,并且减少物品数据以反映正确的库存量。

  • 库存中没有的物品需要订购,这需要与供应商进行某种交互。

  • 关于哪些物品入库(并且可以立即发货)和哪些物品退订,需要通知相应的顾客。

这显然不是一个完整的例子,但足以表达我们的意思了。执行这个处理需要针对许多表的多条SQL语句。此外,需要执行的具体SQL语句及其次序也不是固定的,它们可能会根据物品是否在库存中而变化。

那么,怎样编写代码呢?可以单独编写每条SQL语句,并根据结果有条件地执行其他语句。在每次需要这个处理时(以及每个需要它的应用中),都必须做这些工作。

可以创建存储过程。简单来说,存储过程就是为以后使用而保存的一条或多条SQL语句。可将其视为批文件,虽然它们的作用不仅限于批处理。

说明:不适用于SQLite

SQLite 不支持存储过程。

说明:还有更多内容

存储过程很复杂,全面介绍它需要很大篇幅。市面上有专门讲存储过程的书。本课不打算讲解存储过程的所有内容,只给出简单介绍,让读者对它们的功能有所了解。因此,这里给出的例子只提供Oracle和SQL Server的语法。

2. 为什么要使用存储过程

我们知道了什么是存储过程,那么为什么要使用它们呢?理由很多,下面列出一些主要的:

  • 通过把处理封装在一个易用的单元中,可以简化复杂的操作(如前面例子所述)。

  • 由于不要求反复建立一系列处理步骤,因而保证了数据的一致性。如果所有开发人员和应用程序都使用同一存储过程,则所使用的代码都是相同的。

  • 防止错误。需要执行的步骤越多,出错的可能性就越大。防止错误保证了数据的一致性。

  • 简化对变动的管理。如果表名、列名或业务逻辑(或别的内容)有变化,那么只需要更改存储过程的代码。使用它的人员甚至不需要知道这些变化。

  • 安全性。通过存储过程限制对基础数据的访问,减少了数据讹误(无意识的或别的原因所导致的数据讹误)的机会。

  • 因为存储过程通常以编译过的形式存储,所以DBMS处理命令所需的工作量少,提高了性能。

  • 存在一些只能用在单个请求中的SQL元素和特性,存储过程可以使用它们来编写功能更强更灵活的代码。

换句话说,使用存储过程有三个主要的好处,即简单、安全、高性能。显然,它们都很重要。不过,在将SQL代码转换为存储过程前,也必须知道它的一些缺陷。

  • 不同DBMS中的存储过程语法有所不同。事实上,编写真正的可移植存储过程几乎是不可能的。不过,存储过程的自我调用(名字以及数据如何传递)可以相对保持可移植。因此,如果需要移植到别的DBMS,至少客户端应用代码不需要变动。

  • 一般来说,编写存储过程比编写基本SQL语句复杂,需要更高的技能,更丰富的经验。因此,许多数据库管理员把限制存储过程的创建作为安全措施(主要受上一条缺陷的影响)。

尽管有这些缺陷,存储过程还是非常有用的,并且应该使用。事实上,多数DBMS都带有用于管理数据库和表的各种存储过程。更多信息请参阅具体的DBMS文档。

说明:不会写存储过程?你依然可以使用

大多数DBMS将编写存储过程所需的安全和访问权限与执行存储过程所需的安全和访问权限区分开来。这是好事情,即使你不能(或不想)编写自己的存储过程,也仍然可以在适当的时候执行别的存储过程。

3. 执行存储过程

存储过程的执行远比编写要频繁得多,因此我们先介绍存储过程的执行。执行存储过程的SQL语句很简单,即EXECUTEEXECUTE接受存储过程名和需要传递给它的任何参数。请看下面的例子(你无法运行这个例子,因为AddNewProduct这个存储过程还不存在):

EXECUTE AddNewProduct('JTS01', 'Stuffed Eiffel Tower', 6.49, 'Plush stuffed toy with the text La Tour Eiffel in red white and blue');

分析: 这里执行一个名为AddNewProduct的存储过程,将一个新产品添加到Products表中。AddNewProduct有四个参数,分别是:供应商ID(Vendors表的主键)、产品名、价格和描述。这4个参数匹配存储过程中4个预期变量(定义为存储过程自身的组成部分)。此存储过程将新行添加到Products表,并将传入的属性赋给相应的列。

我们注意到,在Products表中还有另一个需要值的列prod_id列,它是这个表的主键。为什么这个值不作为属性传递给存储过程?要保证恰当地生成此ID,最好是使生成此ID的过程自动化(而不是依赖于最终用户的输入)。这也是这个例子使用存储过程的原因。以下是存储过程所完成的工作:

  1. 验证传递的数据,保证所有4个参数都有值;

  2. 生成用作主键的唯一ID;

  3. 将新产品插入Products表,在合适的列中存储生成的主键和传递的数据。

这就是存储过程执行的基本形式。对于具体的DBMS,可能包括以下的执行选择:

  • 参数可选,具有不提供参数时的默认值。

  • 不按次序给出参数,以"参数=值"的方式给出参数值。

  • 输出参数,允许存储过程在正执行的应用程序中更新所用的参数。

  • SELECT语句检索数据。

  • 返回代码,允许存储过程返回一个值到正在执行的应用程序。

4. 创建存储过程

正如所述,存储过程的编写很重要。为了获得感性认识,我们来看一个简单的存储过程例子,它对邮件发送清单中具有邮件地址的顾客进行计数。

下面是该过程的Oracle版本:

CREATE PROCEDURE MailingListCount (ListCount OUT INTEGER
)
ISv_rows INTEGER;
BEGINSELECT COUNT(*) INTO v_rowsFROM CustomersWHERE NOT cust_email IS NULL;ListCount := v_rows;
END;

分析: 这个存储过程有一个名为ListCount的参数。此参数从存储过程返回一个值而不是传递一个值给存储过程。关键字OUT用来指示这种行为。Oracle支持IN(传递值给存储过程)、OUT(从存储过程返回值,如这里)、INOUT(既传递值给存储过程也从存储过程传回值)类型的参数。存储过程的代码括在BEGINEND语句中,这里执行一条简单的SELECT语句,它检索具有邮件地址的顾客。然后用检索出的行数设置ListCount(要传递的输出参数)。

调用Oracle例子可以像下面这样:

var ReturnValue NUMBER
EXEC MailingListCount(:ReturnValue);
SELECT ReturnValue;

分析: 这段代码声明了一个变量来保存存储过程返回的任何值,然后执行存储过程,再使用SELECT语句显示返回的值。

下面是该过程的SQL Server版本:

CREATE PROCEDURE MailingListCount
ASDECLARE @cnt INTEGERSELECT @cnt = COUNT(*)FROM CustomersWHERE NOT cust_email IS NULL;RETURN @cnt;

分析: 此存储过程没有参数。调用程序检索SQL Server的返回代码提供的值。其中用DECLARE语句声明了一个名为@cnt的局部变量(SQL Server中所有局部变量名都以@起头);然后在SELECT语句中使用这个变量,让它包含COUNT()函数返回的值;最后,用RETURN @cnt语句将计数返回给调用程序。

调用SQL Server例子可以像下面这样:

DECLARE @ReturnValue INT
EXECUTE @ReturnValue = MailingListCount;
SELECT @ReturnValue;

分析: 这段代码声明了一个变量来保存存储过程返回的任何值,然后执行存储过程,再使用SELECT语句显示返回的值。

下面是另一个例子,这次在Orders表中插入一个新订单。此程序仅适用于SQL Server,但它说明了存储过程的某些用途和技术:

CREATE PROCEDURE NewOrder @cust_id CHAR(10)
AS-- 为订单号声明一个变量DECLARE @order_num INTEGER-- 获取当前最大订单号SELECT @order_num = MAX(order_num)FROM Orders-- 决定下一个订单号SELECT @order_num = @order_num + 1-- 插入新订单INSERT INTO Orders(order_num, order_date, cust_id)VALUES(@order_num, GETDATE(), @cust_id)-- 返回订单号RETURN @order_num;

分析: 此存储过程在Orders表中创建一个新订单。它只有一个参数,即下订单顾客的ID。订单号和订单日期这两列在存储过程中自动生成。代码首先声明一个局部变量来存储订单号。接着,检索当前最大订单号(使用MAX()函数)并增加1(使用SELECT语句)。然后用INSERT语句插入由新生成的订单号、当前系统日期(用GETDATE()函数检索)和传递的顾客ID组成的订单。最后,用RETURN @order_num返回订单号(处理订单物品需要它)。请注意,此代码加了注释,在编写存储过程时应该多加注释。

说明:注释代码

应该注释所有代码,存储过程也不例外。增加注释不影响性能,因此不存在缺陷(除了增加编写时间外)。注释代码的好处很多,包括使别人(以及你自己)更容易地理解和更安全地修改代码。

对代码进行注释的标准方式是在之前放置--(两个连字符)。有的DBMS还支持其他的注释语法,不过所有DBMS都支持--,因此在注释代码时最好都使用这种语法。

下面是相同SQL Server代码的一个很不同的版本:

CREATE PROCEDURE NewOrder @cust_id CHAR(10)
AS-- 插入新订单INSERT INTO Orders(cust_id)VALUES(@cust_id)-- 返回订单号SELECT order_num = @@IDENTITY;

分析: 此存储过程也在Orders表中创建一个新订单。这次由DBMS生成订单号。大多数DBMS都支持这种功能;SQL Server中称这些自动增量的列为标识字段(identity field),而其他DBMS称之为自动编号(auto number)或序列(sequence)。传递给此过程的参数也是一个,即下订单的顾客ID。订单号和订单日期没有给出,DBMS对日期使用默认值(GETDATE()函数),订单号自动生成。怎样才能得到这个自动生成的ID?在SQL Server上可在全局变量@@IDENTITY中得到,它返回到调用程序(这里使用SELECT语句)。

可以看到,借助存储过程,可以有多种方法完成相同的工作。不过,所选择的方法受所用DBMS特性的制约。

5. 小结

本文介绍了什么是存储过程,为什么使用存储过程。我们介绍了执行和创建存储过程的语法,使用存储过程的一些方法。存储过程是个相当重要的主题,一课内容无法全部涉及。各种DBMS对存储过程的实现不一,你使用的DBMS可能提供了一些这里提到的功能,也有其他未提及的功能,更详细的介绍请参阅具体的DBMS文档。

相关文章:

SQL使用存储过程

本文介绍什么是存储过程,为什么要使用存储过程,如何使用存储过程,以及创建和使用存储过程的基本语法。 1. 存储过程 迄今为止,我们使用的大多数SQL语句都是针对一个或多个表的单条语句。并非所有操作都这么简单,经常…...

C语言----函数、指针、数组

目录 ​编辑 指针函数 本质 格式: 函数指针 1、 概念 2、 格式 3、 举例 3.1基本用法 3.2函数指针作为函数参数的用法(回调函数) 函数指针数组 1. 概念 2. 格式 3. 例子 指针函数 本质 是函数,返回值为指针 格式: 数据类型…...

基于Java的敬老院管理系统的设计和实现【源码+文档+部署讲解】

基于Java的敬老院管理系统设计和实现 摘 要 新世纪以来,互联网与计算机技术的快速发展,我国也迈进网络化、集成化的信息大数据时代。对于大众而言,单机应用早已成为过去,传统模式早已满足不了当下办公生活等多种领域的需求,在一台电脑上不联网的软件少之又少&#x…...

12306分流抢票软件 bypass v1.16.43 绿色版(春节自动抢票工具)

软件介绍 12306Bypass分流抢票软件,易操作强大的12306抢票软件,全程自动抢票,云识别验证码打码,多线程秒单、稳定捡漏,支持抢候补票、抢到票自动付款,支持多天、多车次、多席别、多乘客、短信提醒等功能。…...

【数据仓库】hadoop3.3.6 安装配置

文章目录 概述下载解压安装伪分布式模式配置hdfs配置hadoop-env.shssh免密登录模式设置初始化HDFS启动hdfs配置yarn启动yarn 概述 该文档是基于hadoop3.2.2版本升级到hadoop3.3.6版本,所以有些配置,是可以不用做的,下面仅记录新增操作&#…...

小试牛刀-SpringBoot集成SOL链

目录 一、什么是solanaj? 二、Pom依赖 三、主要类 3.1 RpcClient 3.2 PublicKey 3.3 Transaction 3.4 TransactionInstruction 四、示例代码 Welcome to Code Blocks blog 本篇文章主要介绍了 [小试牛刀-SpringBoot集成SOL链] ❤博主广交技术好友,喜欢文章的…...

批量插入报错: No value specified for parameter

先上代码和xml文件: 错误: ### Cause: java.sql.SQLException: No value specified for parameter 9 ; bad SQL grammar []; nested exception is java.sql.SQLException: No value specified for parameter 9代码: List<HwcListingData> theList new ArrayList<&g…...

VSCode设置ctrl或alt+mouse(left)跳转

总结&#xff1a; &#xff08;1&#xff09;VSCode初次远程连接服务器时&#xff0c;需要在服务器上下载 python 拓展&#xff0c;然后选择对应的环境 &#xff08;2&#xff09;VSCode设置ctrl或altmouse(left)跳转到定义...

Crosslink-NX应用连载(12):如何复用特殊功能管脚

作者&#xff1a;Hello,Panda 大家早上好。 昨天有朋友私信我&#xff0c;如何复用Crosslink-NX的特殊功能引脚如PROGRAMN、DONE、INITN诸如这些。熊猫君在这里简单介绍下&#xff1a; 以LIFCL-33U-8CTG104C为例&#xff0c;我们建立一个简单的指示灯LED周期闪烁的工程&…...

‘元素.style.样式名‘获取不到样式,应该使用Window.getComputedStyle()获取正真的样式

一、问题描述 有一次&#xff0c;想通过js获取一个元素的样式的某个属性状态而去执行不同的逻辑代码&#xff0c;结果发现获取的样式总是不对&#xff0c;基本为空。&#xff08;通过元素.style.样式名的方式去获取。&#xff09; 通过打印发现&#xff0c;所有的属性均存在&…...

双目视觉:reprojectImageTo3D函数

前言 reprojectImageTo3D 是 OpenCV 中用于从视差图生成三维点云的函数。它的原理是利用视差图和相机的校准参数&#xff0c;通过三角测量法&#xff0c;计算每个像素对应的三维坐标。以下内容根据源码分析所写&#xff0c;觉得可以的话&#xff0c;点赞收藏哈&#xff01;&am…...

Arduino Uno简介与使用方法

目录 一、Arduino Uno概述 1. 硬件特性 2. 开发环境 二、Arduino Uno的基本使用方法 1. 硬件连接 2. 软件编程 三、Arduino Uno编程基础 1. 基本语法 2. 常用函数 四、Arduino Uno应用举例 1. LED闪烁 2. 温度检测 3. 超声波测距 五、Arduino Uno的扩展与应用 1…...

深入了解 StarRocks 表类型:解锁高效数据分析的密码

在当今数字化浪潮下&#xff0c;大数据分析成为企业决策、优化业务流程的关键利器。StarRocks 作为一款备受瞩目的高性能分析型数据库&#xff0c;其多样化的表类型为复杂的数据处理需求提供了精准解决方案。今天&#xff0c;就让我们一同深入探索 StarRocks 中的主键表、明细表…...

L27.【LeetCode笔记】2 的幂(五种解法)

目录 1.题目 2.自解 方法1:调用log函数 代码 提交结果 方法2:循环 提交结果 3.优解 方法3:位运算n & (n-1) 0 代码 提交结果 方法4:位运算lowbit 代码 提交结果 4.投机取巧的方法 代码 提交结果 1.题目 https://leetcode.cn/problems/power-of-two/?env…...

Pentaho Kettle迁移至Oracle的空字符串和NULL的问题处理,大坑!

一、问题说明 在使用 Kettle 将 DB2 数据迁移到 Oracle 的过程中&#xff0c;出现了 DB2 中为空字符串的字段&#xff0c;在插入到 Oracle 过程中实际插入的为 NULL &#xff0c;导致触发了非空校验而迁移失败 空字符串 ‘’ &#xff0c;即长度为0的字符串 搜索该问题后得知…...

「Mac畅玩鸿蒙与硬件50」UI互动应用篇27 - 水果掉落小游戏

本篇教程将带你实现一个水果掉落小游戏&#xff0c;掌握基本的动态交互逻辑和鸿蒙组件的使用&#xff0c;进一步了解事件处理与状态管理。 关键词 UI互动应用水果掉落状态管理动态交互游戏开发 一、功能说明 水果掉落小游戏包含以下交互功能&#xff1a; 随机生成水果&#…...

2.C语言基础:语句、表达式、注释与标准库简介

目录 1.语句2.表达式3.语句块4.空格5.注释6.printf()7.标准库 本篇原文为&#xff1a;C语言基础&#xff1a;语句、表达式、注释与标准库简介 更多C进阶、rust、python、逆向等等教程&#xff0c;可点击此链接查看&#xff1a;酷程网 1.语句 C 语言的代码由一行行语句&#…...

Python 基于 opencv 的人脸识别监控打卡系统(源码+部署)

1. 引言 今天&#xff0c;我们将基于 Python 的 OpenCV 库和 wxPython 框架&#xff0c;构建一个实用的 人脸识别考勤系统。这是一个适合大学生学习的实战项目&#xff0c;功能经过充分调试&#xff0c;确保运行稳定。该系统不仅能帮助你了解人脸识别技术的基本原理&#xff0…...

Maven的依赖管理

1. 依赖管理 依赖管理&#xff0c;可以将有关依赖项的所有信息放在共同的POM中&#xff0c;并对子POM中的工件进行更简单的引用。举个例子&#xff1a; 父POM <project>......<dependencyManagement><dependencies><dependency><groupId>gro…...

数据结构考前一天

线性表&#xff1a;矩阵&#xff0c;链表&#xff08;单链表必考&#xff09; 栈和队列&#xff1a;出入判断&#xff0c;括号匹配&#xff0c;中缀转后缀 字符串数组&#xff1a;模式匹配next&#xff0c;nextval数组&#xff0c;数组寻址&#xff0c;三角矩阵对应一维数组k…...

微信小程序之bind和catch

这两个呢&#xff0c;都是绑定事件用的&#xff0c;具体使用有些小区别。 官方文档&#xff1a; 事件冒泡处理不同 bind&#xff1a;绑定的事件会向上冒泡&#xff0c;即触发当前组件的事件后&#xff0c;还会继续触发父组件的相同事件。例如&#xff0c;有一个子视图绑定了b…...

基于FPGA的PID算法学习———实现PID比例控制算法

基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容&#xff1a;参考网站&#xff1a; PID算法控制 PID即&#xff1a;Proportional&#xff08;比例&#xff09;、Integral&#xff08;积分&…...

STM32+rt-thread判断是否联网

一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

UE5 学习系列(三)创建和移动物体

这篇博客是该系列的第三篇&#xff0c;是在之前两篇博客的基础上展开&#xff0c;主要介绍如何在操作界面中创建和拖动物体&#xff0c;这篇博客跟随的视频链接如下&#xff1a; B 站视频&#xff1a;s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

基于当前项目通过npm包形式暴露公共组件

1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹&#xff0c;并新增内容 3.创建package文件夹...

多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验

一、多模态商品数据接口的技术架构 &#xff08;一&#xff09;多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如&#xff0c;当用户上传一张“蓝色连衣裙”的图片时&#xff0c;接口可自动提取图像中的颜色&#xff08;RGB值&…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面

代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口&#xff08;适配服务端返回 Token&#xff09; export const login async (code, avatar) > {const res await http…...

【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】

1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件&#xff08;System Property Definition File&#xff09;&#xff0c;用于声明和管理 Bluetooth 模块相…...

uniapp微信小程序视频实时流+pc端预览方案

方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度​WebSocket图片帧​定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐​RTMP推流​TRTC/即构SDK推流❌ 付费方案 &#xff08;部分有免费额度&#x…...

多模态大语言模型arxiv论文略读(108)

CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题&#xff1a;CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者&#xff1a;Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...