从Oracle自定义函数和存储过程案例学习PL/SQL的使用

一、什么是PL/SQL


PL/SQL(Procedural Language/Structured Query Language) 是Oracle数据库对SQL的扩展,它在SQL的基础上增加了过程化编程语言的元素,如变量、条件语句、循环语句、异常处理等。这使得PL/SQL不仅可以用于查询数据,还可以用于控制数据以及实现复杂的业务逻辑。

二、Oracle自定义函数案例分析

案例一

/*综述:大小值校验入参:checkcolumn:校验列列名    lowvalue:小值    highvalue:大值  isinclude:是否包含边界 1是 0否输出: 布尔值,判断通过与否 0不通过 1通过判断内容:1、判断校验列列名checkcolumn是否为数值型,如为非数值型-->0不通过;A.判断小值lowvalue<校验列列名checkcolumn<大值highvalue-->1通过;B.当小值为空,大值不为空时,判断校验列列名checkcolumn<大值highvalue-->1通过;C.当大值为空,小值不为空时,判断小值lowvalue<校验列列名checkcolumn-->1通过;*/-- 具体实现CREATE OR REPLACE function LKTEST.SizeValueVerify(
checkcolumn IN varchar2, 
lowvalue IN numeric,
highvalue IN numeric
)RETURN integer ISv_checkcolumn numeric;
BEGINif checkcolumn is null thenreturn null;end if;v_checkcolumn := to_number(checkcolumn);if lowvalue is not null and highvalue is not null and v_checkcolumn>lowvalue and v_checkcolumn<highvalue thenreturn 1;elsif lowvalue is null and highvalue is not null and v_checkcolumn<highvalue thenreturn 1;elsif lowvalue is not null and highvalue is null and v_checkcolumn>lowvalue thenreturn 1;elsereturn 0;end if ;--异常捕获EXCEPTIONWHEN OTHERS THENRETURN 0;END;

逐步分析

函数的定义部分
CREATE OR REPLACE function LKTEST.SizeValueVerify(  
checkcolumn IN varchar2,  
lowvalue IN numeric,  
highvalue IN numeric  
)  RETURN integer
  • CREATE OR REPLACE FUNCTION LKTEST.SizeValueVerify: 创建一个名为SizeValueVerify的函数在LKTEST模式下,如果该函数已经存在,则替换它。
  • 输入参数有三个:
    • checkcolumn IN varchar2: 一个字符串类型的输入参数,表示要校验的列名(但这里实际上应该是列的值,因为列名在运行时是未知的)。
    • lowvalue IN numeric: 一个数值类型的输入参数,表示校验的低值。
    • highvalue IN numeric: 一个数值类型的输入参数,表示校验的高值。
  • 函数返回一个整数类型的值。
函数的变量声明部分
 
IS  v_checkcolumn numeric;  
  • v_checkcolumn numeric;: 声明了一个名为v_checkcolumn的数值型变量,用于存储转换后的checkcolumn值。
函数的主体部分
if checkcolumn is null then  return null;  
end if;

如果checkcolumn(实际上是列的值)为null,则函数返回null。

v_checkcolumn := to_number(checkcolumn);

尝试将checkcolumn(字符串)转换为数值并存储在v_checkcolumn中。

if lowvalue is not null and highvalue is not null and v_checkcolumn>lowvalue and v_checkcolumn<highvalue then  return 1;  
...  
end if;

这是主要的判断逻辑:

  • 如果lowvaluehighvalue都不为空,并且v_checkcolumn的值在这两个值之间(不包括边界),则返回1。
  • 接下来的两个elsif子句处理了当其中一个边界值为null的情况。
--异常捕获  
EXCEPTION  WHEN OTHERS THEN  RETURN 0;

这是异常处理部分。如果函数中的任何代码抛出了异常(例如,当to_number(checkcolumn)失败时),则捕获该异常并返回0。

根据案例总结PL/SQL语法

  • IS关键字之后的部分是函数的声明部分,其中你可以声明局部变量、常量、游标等。然后,BEGINEND之间的部分是函数体,其中包含了函数的具体逻辑。简而言之,IS(或AS)在PL/SQL函数和过程中用于分隔参数列表和函数体。这是Oracle PL/SQL的语法要求之一。
  • 在PL/SQL中,IF 语句下面可以跟随任意数量的语句,这些语句被包含在 BEGIN ... END; 块中(如果有多于一个语句的话)。如果没有 BEGIN ... END; 块,则 IF 语句只能直接跟随一个单独的语句。
  • PL/SQL中BEGIN ... END; 块相当于就是Java中的"{" 和 "}"。
  • end if  也相当于Java中的"}",代表语句块的结束。
  • ":="是PL/SQL中的赋值符号,等价于Java中的"=";PL/SQL中的"="可以理解为Java中的"=="。
  • 函数中是先对函数进行了声明,然后声明了变量。再开始在BEGIN ... END;块中写执行过程,其中BEGIN ... END;块还可以嵌套使用BEGIN ... END;块。
  • WHEN OTHERS THEN是一个通用的异常处理器,它会捕获在BEGINEND之间发生的任何未被其他特定异常处理器捕获的异常。当发生这样的异常时,代码将执行RETURN 0;,这意味着函数将返回一个值0,而不是继续执行或抛出异常到调用者。

    使用WHEN OTHERS THEN需要谨慎,因为它会捕获所有的异常,这可能会隐藏一些你不希望忽略的潜在问题。通常,最好编写特定的异常处理器来处理你期望可能会发生的异常,并只使用WHEN OTHERS THEN作为最后的手段来捕获并处理那些你未明确处理的异常。

PL/SQL中变量的声明方式

在PL/SQL中,IS(或AS)和DECLARE在函数和过程的上下文中具有不同的用途和位置。

  • 在函数和过程中
    • 函数和过程的定义通常以CREATE OR REPLACE FUNCTIONCREATE OR REPLACE PROCEDURE开始。
    • 在参数列表和返回类型之后,你会看到IS(或AS),这标志着函数或过程的参数和返回类型的结束,以及函数体或过程体的开始。
    • IS(或AS)之后和BEGIN之前,你可以直接声明局部变量、常量、游标等,而不需要使用DECLARE关键字。
CREATE OR REPLACE FUNCTION my_function (param1 IN NUMBER) RETURN NUMBER IS  v_my_variable NUMBER;  -- 直接声明变量,不需要DECLARE  
BEGIN  ...  
END my_function;  
/
  • 在匿名块中
    • 匿名块是直接在SQL*Plus、SQL Developer或其他工具中执行的PL/SQL代码块。
    • 在匿名块中,如果你想声明局部变量、常量或游标,你需要使用DECLARE关键字。
    • DECLARE部分位于BEGIN之前。
DECLARE  v_my_variable NUMBER;  -- 使用DECLARE声明变量  
BEGIN  ...  
END;  
/
  • 总结
    • 在函数和过程中,你不需要使用DECLARE来声明局部变量,而是直接在IS(或AS)之后声明它们。
    • 在匿名块中,你需要使用DECLARE来声明局部变量。

PL/SQL中异常处理方式

  • 预定义异常

Oracle预定义了一些异常,如NO_DATA_FOUNDTOO_MANY_ROWSZERO_DIVIDE等。这些异常在特定情况下自动触发。

DECLARE  v_count NUMBER;  
BEGIN  SELECT COUNT(*) INTO v_count FROM employees WHERE employee_id = 100;  IF v_count = 0 THEN  RAISE NO_DATA_FOUND; -- 实际上,上面的SELECT语句在找不到行时会自动触发NO_DATA_FOUND异常  END IF;  
EXCEPTION  WHEN NO_DATA_FOUND THEN  DBMS_OUTPUT.PUT_LINE('没有找到员工ID为100的员工。');  
END;

注意:在上面的示例中,我们实际上不需要手动触发NO_DATA_FOUND异常,因为当SELECT INTO语句没有找到任何行时,Oracle会自动触发它。

  • 用户自定义异常

你可以定义自己的异常,并在代码中显式地触发它们。

DECLARE  invalid_id EXCEPTION;  v_employee_id NUMBER := -1;  
BEGIN  IF v_employee_id < 0 THEN  RAISE invalid_id;  END IF;  
EXCEPTION  WHEN invalid_id THEN  DBMS_OUTPUT.PUT_LINE('员工ID无效。');  
END;
  • 使用PRAGMA EXCEPTION_INIT为用户定义异常关联错误号

你可以使用PRAGMA EXCEPTION_INIT为用户定义的异常关联一个Oracle错误号。

DECLARE  my_custom_exception EXCEPTION;  PRAGMA EXCEPTION_INIT(my_custom_exception, -20001); -- 关联自定义异常与错误号-20001  
BEGIN  -- 假设这里有一些可能触发错误号-20001的代码  -- ...  RAISE_APPLICATION_ERROR(-20001, '这是一个自定义错误消息'); -- 触发错误号-20001  
EXCEPTION  WHEN my_custom_exception THEN  DBMS_OUTPUT.PUT_LINE('捕获到自定义异常:' || SQLERRM);  
END;
  • 使用WHEN OTHERS THEN捕获所有其他异常

WHEN OTHERS THEN子句可以捕获所有未被前面WHEN子句捕获的异常。

BEGIN  -- 这里有一些可能引发异常的代码  -- ...  
EXCEPTION  WHEN NO_DATA_FOUND THEN  DBMS_OUTPUT.PUT_LINE('没有找到数据。');  WHEN OTHERS THEN  DBMS_OUTPUT.PUT_LINE('发生了一个未知异常:' || SQLERRM);  
END;
  • 在异常处理中回滚事务

如果在事务中发生异常,并且你希望撤销该事务中所有未提交的更改,可以使用ROLLBACK语句。

DECLARE  PRAGMA AUTONOMOUS_TRANSACTION; -- 如果需要的话,声明为自治事务  
BEGIN  -- 开始一个事务  -- ...(一些DML操作)  -- 假设这里发生了异常  RAISE_APPLICATION_ERROR(-20002, '事务中的错误');  EXCEPTION  WHEN OTHERS THEN  ROLLBACK; -- 回滚事务  DBMS_OUTPUT.PUT_LINE('事务已回滚:' || SQLERRM);  
END;

 三、Oracle存储过程案例分析

案例一

假设我们有一个名为employees的表,其结构如下:

CREATE TABLE employees (  employee_id NUMBER PRIMARY KEY,  first_name VARCHAR2(50),  last_name VARCHAR2(50),  email VARCHAR2(100),  phone_number VARCHAR2(20)  
);

现在,我们可以创建一个存储过程来查询这个表:

CREATE OR REPLACE PROCEDURE sp_get_employee_details(  p_employee_id IN NUMBER,  p_first_name OUT VARCHAR2,  p_last_name OUT VARCHAR2,  p_email OUT VARCHAR2,  p_phone_number OUT VARCHAR2  
) AS  
BEGIN  SELECT first_name, last_name, email, phone_number  INTO p_first_name, p_last_name, p_email, p_phone_number  FROM employees  WHERE employee_id = p_employee_id;  -- 如果员工不存在,可以抛出一个异常或者设置一些错误标志,但这里为了简单起见,我们不会这样做  -- 你可以在调用这个存储过程的PL/SQL块中处理NO_DATA_FOUND异常  
EXCEPTION  WHEN NO_DATA_FOUND THEN  -- 你可以在这里处理员工不存在的情况  DBMS_OUTPUT.PUT_LINE('No employee found with the given ID.');  -- 或者你可以抛出一个自定义的异常  -- RAISE_APPLICATION_ERROR(-20001, 'No employee found with the given ID.');  
END sp_get_employee_details;  
/

 

注意:

  1. 我们使用了INOUT参数来定义输入和输出参数。在这个例子中,p_employee_id是输入参数,而其他四个参数是输出参数。
  2. 我们使用SELECT ... INTO ...语句从employees表中检索数据,并将结果存储在输出参数中。
  3. 如果在表中找不到与给定ID匹配的员工,SELECT ... INTO ...语句将引发NO_DATA_FOUND异常。在这个例子中,我们只是简单地使用DBMS_OUTPUT.PUT_LINE打印一条消息,但你可以根据你的需求选择其他处理方式。

要调用这个存储过程并处理结果,你可以使用以下PL/SQL块:

DECLARE  v_first_name VARCHAR2(50);  v_last_name VARCHAR2(50);  v_email VARCHAR2(100);  v_phone_number VARCHAR2(20);  
BEGIN  sp_get_employee_details(123, v_first_name, v_last_name, v_email, v_phone_number);  -- 这里你可以使用检索到的员工详细信息  DBMS_OUTPUT.PUT_LINE('First Name: ' || v_first_name);  DBMS_OUTPUT.PUT_LINE('Last Name: ' || v_last_name);  DBMS_OUTPUT.PUT_LINE('Email: ' || v_email);  DBMS_OUTPUT.PUT_LINE('Phone Number: ' || v_phone_number);  
EXCEPTION  WHEN OTHERS THEN  DBMS_OUTPUT.PUT_LINE('An error occurred: ' || SQLERRM);  
END;  
/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/863530.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[小试牛刀-习题练]《计算机组成原理》之数据信息的表示、运算方法与运算器

【数据信息的表示运算方法与运算器】 1、【机器码转换】X-0.11111111&#xff0c;X的补码是 1.00000001 。 最高位符号位为负值&#xff1a; 反码法——绝对值按位取反末位加一&#xff0c;1.000000000.000000011.00000001扫描法——从右往左找到第一个为1的&#xff…

常用字符串方法<python>

导言 在python中内置了许多的字符串方法&#xff0c;使用字符串方法可以方便快捷解决很多问题&#xff0c;所以本文将要介绍一些常用的字符串方法。 目录 导言 string.center(width[,fillchar]) string.capitalize() string.count(sub[,start[,end]]) string.join(iterabl…

ffmpeg编码图象时报错Invalid buffer size, packet size * < expected frame_size *

使用ffmpeg将单个yuv文件编码转为jpg或其他图像格式时&#xff0c;报错&#xff1a; Truncating packet of size 11985408 to 3585 [rawvideo 0x1bd5390] Packet corrupt (stream 0, dts 1). image_3264_2448_0.yuv: corrupt input packet in stream 0 [rawvideo 0x1bd7c60…

在本地和Linux之间传输文件

1.打开本地的cmd窗口 2. 然后按这个链接的说法在cmd中远程连接Linux&#xff08;技术|如何在 Linux 中使用 sFTP 上传或下载文件与文件夹&#xff09; 3. 看这个链接里面的sftp命令进行本地和Linux之间的文件互传 &#xff08;https://www.cnblogs.com/niuben/p/13324099.htm…

【嵌入式CLion】进阶调试——WSL下的Linux体验

说明&#xff1a; 1&#xff0c;这里所指的嵌入式其实是指嵌入式微控制器MCU&#xff0c;即单片机 2&#xff0c;万事开头难&#xff0c;本文目前提供了WSL工具链的搭建&#xff0c;后面会持续更新 一、启用RTOS集成 在搭建WSL工具链之前&#xff0c;先讲一下集成的RTOS功能&a…

D-MAX纠偏软件Fife MAX Terminal软件MAX-Oi软件

D-MAX纠偏软件Fife MAX Terminal软件MAX-Oi软件

无理数的本质:一维无法理解更高维

无理数是那些不能表示为两个整数的比的数&#xff0c;其小数部分是无限不循环的&#xff0c;常见的无理数有 π、√2 等。 如果从更本质一点的角度来理解&#xff0c;无理数的出现是因为一维无法完全理解更高维。更高维的“长度”映射到一维&#xff0c;可能出现映射不完全的情…

python r, b, u, f 前缀详解

1、r前缀 一般来说&#xff0c;\n’是一个换行符&#xff0c;是一个字符串&#xff1b;而加上r为前缀后&#xff0c;不会以任何特殊方式处理反斜杠。因此&#xff0c;r"\n" 是包含 ‘\’ 和 ‘n’ 的双字符字符串&#xff1b;示例如下&#xff1a; >>> pr…

SpringBoot的自动配置核心原理及拓展点

Spring Boot 的核心原理几个关键点 约定优于配置&#xff1a; Spring Boot 遵循约定优于配置的理念&#xff0c;通过预定义的约定&#xff0c;大大简化了 Spring 应用程序的配置和部署。例如&#xff0c;它自动配置了许多常见的开发任务&#xff08;如数据库连接、Web 服务器配…

8080时序驱动TFT显示屏 驱动IC GC9307

8080时序总共有控制线 CS片选线 DC(命令数据控制线) RD读控制线 WR写控制线 和N条数据线。 控制底层代码如下; 写读代码,读的代码反过来就行 inline void TFT8080WriteDat(unsigned char dat) {CS_L;//开始片选DC_H;//写数据 // RD_H;//禁止读WR_H;//禁止写WR_L;//写入…

低空经济腾飞:无人机空域申请流程及策略

一、引言 随着低空经济的快速发展&#xff0c;无人机已广泛应用于各个领域&#xff0c;包括航拍、物流、农业、科研等。为了保障飞行安全、维护空中交通秩序&#xff0c;各国纷纷出台了无人机飞行管理规定。本文将详细介绍无人机空域申请的流程及策略&#xff0c;帮助无人机运…

通过Python脚本实现字符画

效果 讲解&#xff1a; 用于将3D视图的帧缓冲区转换为字符画&#xff0c;并将字符画输出到文本编辑器中。 首先&#xff0c;获取当前绑定的帧缓冲区、视口信息和视图像素。 然后&#xff0c;将像素矩阵转化为字符串&#xff0c;并将字符串写入到文本编辑器中。 设置文本编辑…

bmob Harmony快速开发手机号一键登录功能

最近用Bmob的鸿蒙SDK尝试了Harmony开发&#xff0c;做了一个几乎每个应用都会有的功能&#xff1a;手机号码短信验证码一键注册登录的功能&#xff0c;感觉简直爽的不要不要的&#xff0c;ArkUI可见即可得的UI交互设计体验&#xff0c;配合Bmob后端云一如既往简单易用的风格&am…

使用Perplexity打造产品的27种方式

ChatGPT和Perplexity等聊天机器人正迅速成为产品经理的首选助手。以下是一份全面的指南&#xff0c;介绍PM如何在日常工作中使用Perplexity&#xff0c;该指南基于300多份回复和30次电话后的总结。 理解并制定增长战略&#xff1a;例如&#xff0c;解释增长会计的基本原理&…

【Vue】——组件之间数据的传递

&#x1f4bb;博主现有专栏&#xff1a; C51单片机&#xff08;STC89C516&#xff09;&#xff0c;c语言&#xff0c;c&#xff0c;离散数学&#xff0c;算法设计与分析&#xff0c;数据结构&#xff0c;Python&#xff0c;Java基础&#xff0c;MySQL&#xff0c;linux&#xf…

MySQL触发器教程(02):创建删除后触发器

文章目录 介绍语法使用场景示例创建students表创建scores表创建删除触发器 结论 介绍 MySQL 触发器是一种数据库对象&#xff0c;可以在特定的数据库表上自动执行一系列的操作&#xff0c;例如插入、更新或删除数据&#xff0c;当特定的事件&#xff08;例如数据的插入、更新或…

ES6面试题——var,let,const的区别

它们都是用来声明变量的。 1. var具有变量提升机制&#xff0c;let和const没有 /* var有变量提升机制 */ <script> console.log(str); // 打印出undefined var str "你好"; </script>/* let没有变量提升机制 */ <script> console.log(str); // …

【proteus经典实战】16X192点阵程序

一、简介 6X192点阵程序通常用于表示高分辨率图像或文字&#xff0c;其中16X表示像素阵列的宽度&#xff0c;192表示每个像素阵列中的点阵数&#xff0c;16X192点阵程序需要一定的编程知识和技能才能编写和调试&#xff0c;同时还需要考虑硬件设备的兼容性和性能等因素。 初始…

知识不成体系?这篇Mysql数据库将成为你的解忧杂货店!(子查询)

欢迎来到一夜看尽长安花 博客&#xff0c;您的点赞和收藏是我持续发文的动力 对于文章中出现的任何错误请大家批评指出&#xff0c;一定及时修改。有任何想要讨论的问题可联系我&#xff1a;3329759426qq.com 。发布文章的风格因专栏而异&#xff0c;均自成体系&#xff0c;不足…

网线直连电脑可以上网,网线连tplink路由器上不了网

家里wifi网络连不上好几天了&#xff0c;用网线直连电脑可以上网&#xff0c;但网线连tplink路由器wan口上不了网&#xff0c;无Internet连接&#xff0c;网线连lan口可以电脑上网&#xff0c;手机上不了。 后来发现网线的主路由用的192.168.0.1&#xff0c;我的路由器wan口自…