PL/SQL 异常处理

目录

一、命名的系统异常

1.常见命名的系统异常

 2.预定义的系统异常数量以及描述

3.处理命名的系统异常的一般步骤

二、程序员定义的异常

1.概念

 2.自定义异常的定义与抛出

 3.自定义异常的处理

三、未命名的系统异常 

 1.概述

 2.处理未命名的系统异常的方法

3.使用场景 

四、未命名的程序员自定义的异常

1.概述

2.作用

3. 使用方法及示例

未命名的程序员自定义异常与程序员定义异常的区别 

1.声明与抛出

2.错误代码和信息

3.使用场景 


引言 

在设计PL/SQL程序时,经常会发生这样或者那样的错误,异常处理就是针对错误进行处理的程序段,Oracle中的异常处理分为系统预定义异常处理和自定义异常处理两部分。

 异常的类型大概分为四类:

1.命名的系统异常

2.程序员定义的异常

3.未命名的系统异常

4.未命名的程序员定义的异常

一、命名的系统异常

命名的系统异常是Oracle数据库为了处理常见的错误情况而预定的一组异常。它们由Oracle数据库在特定条件下自动抛出,开发者就可以在PL/SQL程序中通过异常机制来捕获和处理这些异常。

1.常见命名的系统异常

NO_DATA_FOUND

错误代码:ORA-01403

错误描述:当执行SELECT INTO语句时,如果没有返回任何数据,就会抛出此异常。

示例:

DECLAREv_name varchar(10);
BEGINSELECT s_name INTO v_name from Students WHERE s_id = '001';
EXCEPTIONWHEN NOT_DATA_FOUND THENDBMS_OUTPUT.PUT_LINE('未找到编号为001的学生');
END;

TOO_MANY_ROWS 

错误代码:ORA-01422

 描述:当执行SELECT INTO语句时,如果返回多行,则会抛出异常。

示例:

DECLAREv_name varchar(10);
BEGINSELECT s_name INTO v_name from Students WHERE s_id = '001';
EXCEPTIONWHEN TOO_MANY_ROWS THENDBMS_OUTPUT.PUT_LINE('有多个编号为001的学生');
END;

 2.预定义的系统异常数量以及描述

数量:大约24种。

异常名称异常编号(SQLCODE)描述
ACCESS_INTO_NULL-6530尝试为未初始化的对象属性赋值时触发。
CASE_NOT_FOUND-6592CASE语句中没有匹配的WHEN子句且没有设置ELSE子句时触发。
COLLECTION_IS_NULL-6531尝试使用未初始化的集合元素时触发。
CURSOR_ALREADY_OPEN-6511尝试打开一个已经打开的游标时触发。
DUP_VAL_ON_INDEX-1尝试插入或更新数据时,唯一索引对应的列上有重复的值时触发。
INVALID_CURSOR-1001尝试使用无效的游标时触发。
INVALID_NUMBER-1722尝试将字符转换为数字失败时触发。
LOGIN_DENIED-1017尝试使用无效的用户名或密码登录Oracle数据库时触发。
NO_DATA_FOUND-1403SELECT INTO语句未返回任何数据时触发。
NOT_LOGGED_ON-1012尝试在未登录的情况下访问Oracle数据库时触发。
PROGRAM_ERROR-6501PL/SQL内部错误,可能需要重装数据字典或PL/SQL系统包时触发。
ROWTYPE_MISMATCH-6504宿主游标变量与PL/SQL游标变量的返回类型不兼容时触发。
SELF_IS_NULL-(无固定编号)使用对象类型时,在NULL对象上调用对象方法时触发。
STORAGE_ERROR-6500运行PL/SQL时,超出内存空间或内存被破坏时触发。
SUBSCRIPT_BEYOND_COUNT-6533尝试访问嵌套表或VARRAY时,元素下标超出最大值时触发。
SUBSCRIPT_OUTSIDE_LIMIT-6532使用嵌套表或VARRAY时,元素下标为负数时触发。
SYS_INVALID_ID-1410尝试使用无效的ROWID字符串时触发。
TIMEOUT_ON_RESOURCE-51等待资源时超时触发。
TOO_MANY_ROWS-1422SELECT INTO语句返回多行时触发。
VALUE_ERROR-6502赋值时,变量长度不足以容纳实际数据时触发。
ZERO_DIVIDE-1476尝试执行除数为零的除法运算时触发。
CURSOR_IS_OPEN-(非标准,示例)尝试在游标已打开的情况下进行非法操作(如重复打开)时触发。
COLLECTION_IS_LOCKED-(非标准,示例)尝试访问已锁定的集合元素时触发。
INVALID_TRANSACTION-(非标准,示例)尝试执行无效的事务操作时触发。
NETWORK_ERROR-(非标准,示例)网络通信错误时触发。

说明

  1. 异常编号(SQLCODE):Oracle数据库为每种异常分配了一个唯一的错误编号(SQLCODE),用于标识该异常。在异常处理中,可以通过捕获异常编号来判断具体的错误类型。

  2. 异常名称:Oracle数据库为每种异常提供了一个名称,便于开发人员在代码中引用和处理。

  3. 描述:简要说明了触发每种异常的条件和场景。

  4. 非标准异常:上述列表中最后几种异常(如CURSOR_IS_OPENCOLLECTION_IS_LOCKEDINVALID_TRANSACTIONNETWORK_ERROR)是示例性的,用于说明可能的异常类型,并非Oracle数据库标准预定义的异常。实际开发中,这些异常可能需要开发人员根据业务需求自定义。

  5. 异常处理:在PL/SQL程序中,可以通过EXCEPTION块来捕获和处理这些预定义异常,以确保程序的健壮性和可靠性。

3.处理命名的系统异常的一般步骤

捕获异常:在PL/SQL程序中,使用EXCEPTION块来捕获可能抛出的命名系统异常。

处理异常:在捕获到异常后,执行相应的处理逻辑,如输出错误信息、记录日志、回滚事务等。

继续执行或者退出程序:根据需求,决定是继续执行后续代码还是退出程序。一旦进EXCEPTION块,后续的代码(指在BEGIN ... END块中EXCEPTION部分之后的代码)将不会被执行。(这过程简直和Java一摸一样)

示例:

DECLAREv_error_occurred BOOLEAN := FALSE;--变量v_error_occurred用于跟踪是否发生了错误,以便在后续代码中采取适当的操作。
BEGIN-- 尝试执行一些可能引发异常的代码BEGIN-- 这里是可能抛出异常的代码RAISE NO_DATA_FOUND; -- 示例异常EXCEPTIONWHEN NO_DATA_FOUND THENDBMS_OUTPUT.PUT_LINE('No data found, continuing with the next step.');v_error_occurred := TRUE; -- 标记错误已发生END;-- 后续的代码,无论是否发生异常都会执行IF v_error_occurred THENDBMS_OUTPUT.PUT_LINE('An error occurred, but we are continuing with the process.');END IF;DBMS_OUTPUT.PUT_LINE('This is the subsequent code that will always be executed.');-- 更多的后续代码...
END;

二、程序员定义的异常

1.概念

自定义异常是程序员根据业务逻辑需求,在PL/SQL程序中显示声明的异常。当程序中出现特定条件时,程序员可以显式地抛出这些自定义异常,并在异常处理部分(EXCEPTION)进行捕获和处理。

 2.自定义异常的定义与抛出

定义异常:在块声明部分,使用DECLARE关键字声明异常

DECLAREmy_custom_exception EXCEPTION;

 抛出异常:在程序执行部分,使用RAISE语句抛出自定义异常。

BEGINIF condition THENRAISE my_custom_exception;END IF

 3.自定义异常的处理

捕获异常:在EXCEPTION块中,使用WHEN...TEHN语句捕获并处理自定义异常。

EXCEPTION   WHEN my_custom_exception THENDBMS_OUTPUT.PUT_LINE('自定义异常被触发');--处理异常,记录日志,事务回滚等
END

与其他异常一起处理:在EXCEPTION块中,程序员可以捕获和处理多种异常,包括预定义异常和自定义异常。

EXCEPTIONWHEN NO_DATA_FOUND THENDBMS_OUTPUT.PUT_LINE('未找到数据');WHEN my_custom_exception THENDBMS_OUTPUT.PUT_LINE('自定义异常被触发');WHEN OTHERS THENDBMS_OUTPUT.PUT_LINE('发生其他异常: ' || SQLERRM);

OTHERS子句用于捕获和处理所有未显式捕获的异常。

三、未命名的系统异常 

在PL/SQL中,未命名的系统异常是指那些由Oracle数据库系统内部产生的、没有预定义异常名称的错误。这些异常通常以错误代码(Oracle错误号)的形式出现,而没有与之直接对应的异常名。为了处理这些未命名的系统异常,PL/SQL提供了相应的机制和语法。

 1.概述

未命名的系统异常通常是由于违反Oracle数据库的内部规则或系统限制而产生的。这些异常没有预定义的异常名称,但Oracle数据库为每个异常分配了一个唯一的错误代码(Oracle错误号)。例如,当尝试删除一个具有子记录的父表记录时,Oracle会抛出错误代码为-2292的未命名系统异常。

 2.处理未命名的系统异常的方法

声明异常名称:使用EXCEPTION关键字声明一个自定义的异常名称。

DECLAREchild_record_exception EXCEPTION

将异常名称与错误代码关联:使用PRAGMA EXCEPTION_INT伪指令将自定义的异常名称与未命名的系统异常的错误代码关联起来。

PRAGMA EXCEPTION_INIT(child_record_exception, -2292);

在异常处理部分捕获异常

在PL/SQL块的异常处理部分,使用WHEN关键字捕获自定义的异常名称,并执行相应的处理逻辑。

BEGIN-- 执行可能导致异常的操作,例如删除具有子记录的父表记录DELETE FROM parent_table WHERE id = 1;
EXCEPTIONWHEN child_record_exception THENDBMS_OUTPUT.PUT_LINE('无法删除父记录,因为存在子记录。');
END;

 完整示例

DECLAREchild_record_exception EXCEPTION;PRAGMA EXCEPTION_INIT(child_record_exception, -2292);
BEGIN-- 尝试删除一个具有子记录的父表记录DELETE FROM departments WHERE department_id = 10;
EXCEPTIONWHEN child_record_exception THENDBMS_OUTPUT.PUT_LINE('无法删除父记录,因为存在子记录。');WHEN OTHERS THENDBMS_OUTPUT.PUT_LINE('发生其他异常:' || SQLERRM);
END;

3.使用场景 

  1. 处理特定的系统错误Oracle数据库在运行时会产生各种系统错误,这些错误通常以错误代码的形式出现,而没有与之直接对应的异常名。例如,当尝试删除一个具有子记录的父表记录时,Oracle会抛出错误代码为-2292的系统错误。为了处理这种特定的系统错误,可以使用未命名的系统异常。

  2. 增强代码的可读性和可维护性通过为未命名的系统异常定义一个明确的异常名称,并使用PRAGMA EXCEPTION_INIT伪指令将其与错误代码关联起来,可以使代码更加清晰易懂。这样,在异常处理部分,就可以直接使用自定义的异常名称,而不需要记住复杂的错误代码。

  3. 实现更细粒度的异常处理:在PL/SQL中,可以使用WHEN OTHERS子句来捕获所有未捕获的异常。然而,这种方式过于笼统,可能无法准确地定位问题。通过为特定的系统错误定义未命名的系统异常,可以实现更细粒度的异常处理,从而更好地定位问题并采取适当的解决措施。

四、未命名的程序员自定义的异常

1.概述

RAISE_APPLICATION_ERROR 在 Oracle PL/SQL 中用于引发用户自定义的异常。它主要用于在应用程序中主动抛出自定义的错误代码和错误消息,以便更好地处理异常情RAISE_APPLICATION_ERROR 引发的是用户自定义的异常。 这种异常不是由 Oracle 系统自动抛出的,而是由开发人员根据业务需求,在 PL/SQL 代码中显式抛出的。

2.作用

提供详细的错误信息RAISE_APPLICATION_ERROR 允许开发人员自定义错误代码和错误消息。这样,当异常被抛出时,调用程序可以接收到更详细、更有意义的错误信息,而不是仅仅依赖于 Oracle 的标准错误消息。

增强错误处理灵活性:通过引发自定义异常,开发人员可以更灵活地控制错误处理流程。例如,可以在不同的业务逻辑分支中抛出不同的异常,以便调用程序根据异常类型采取相应的处理措施。

提高程序的可维护性:使用 RAISE_APPLICATION_ERROR 可以将错误处理逻辑与业务逻辑分离,使得程序更加清晰易读。同时,自定义的异常处理机制也便于后续的代码维护和升级。

3. 使用方法及示例

基本语法

RAISE_APPLICATION_ERROR(error_number,error_message [, kee_error]);
  • error_number:自定义的错误代码,必须是一个介于 -20000 和 -20999 之间的整数。这个范围内的错误代码不会与 Oracle 的保留错误代码冲突。

  • error_message:自定义的错误消息,是一个字符串。该消息的长度不应超过 2048 个字符。它将被传递给调用程序,以便调用程序了解异常的具体原因。

  • keep_errors(可选):这是一个布尔值参数,用于指示是否将当前的错误堆栈信息包含在异常中。在 Oracle 12c 及更高版本中引入。如果设置为 FALSE(默认值),则当前的错误信息会替换已有的错误堆栈。如果设置为 TRUE,则当前的错误信息会被添加到已有的错误堆栈中。

使用示例

 假设我们有一个存储过程,用于检查员工的薪水是否低于某个最低值。如果薪水低于最低值,则使用 RAISE_APPLICATION_ERROR 抛出异常:

CREATE OR REPLACE PROCEDURE check_salary (p_emp_id IN NUMBER, p_min_salary IN NUMBER) ISv_salary NUMBER;
BEGIN-- 查询员工薪水SELECT salary INTO v_salary FROM employees WHERE employee_id = p_emp_id;-- 检查薪水是否低于最低值IF v_salary < p_min_salary THEN-- 抛出自定义异常RAISE_APPLICATION_ERROR(-20001, 'Employee salary is below the minimum required.');END IF;EXCEPTIONWHEN NO_DATA_FOUND THEN-- 处理未找到员工数据的情况RAISE_APPLICATION_ERROR(-20002, 'Employee ID not found.');
END;

未命名的程序员自定义异常与程序员定义异常的区别 

1.声明与抛出

  • 自定义异常需要先声明,然后才能抛出。声明是在 PL/SQL 块的声明部分进行的,而抛出是在执行部分进行的。
  • RAISE_APPLICATION_ERROR 则不需要事先声明异常,它直接在执行部分抛出自定义的错误代码和消息。

2.错误代码和信息

  • 自定义异常本身不包含错误代码和消息,这些需要在抛出异常时通过其他方式(如注释或文档)进行说明。
  • RAISE_APPLICATION_ERROR 则直接包含了错误代码和消息,使得异常信息更加完整和直观。

3.使用场景 

  • 自定义异常更适合用于处理那些与 Oracle 系统错误无关的业务逻辑错误,例如数据验证失败、业务规则违反等。
  • RAISE_APPLICATION_ERROR 则更适合用于处理那些需要自定义错误代码和消息的异常情况,例如当应用程序需要向用户显示特定的错误消息时。

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

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

相关文章

网络原理-

文章目录 协议应用层传输层网络层 数据链路层 协议 在网络通信中,协议是非常重要的概念.协议就是一种约定. 在网络通信过程中,对协议进行了分层 接下来就按照顺序向大家介绍每一种核心的协议. 应用层 应用层是咱们程序员打交道最多的一层协议.应用层里有很多现成的协议,但…

【面试】Java面试频繁问到的题最新整理(附答案)

文章目录 一、Java基础部分面试题 1.1. Java面向对象的三个特征1.2. Java中基本的数据类型有哪些 以及他们的占用字节1.3. int和Integer的区别1.4. String、StringBuilder、StringBuffer的区别及使用场景1.5. ArrayList、Vector和LinkedList的区别及使用场景1.6. Collection和…

从零搭建微服务项目Base(第7章——微服务网关模块基础实现)

前言&#xff1a; 在前面6章的学习中已经完成了服务间的调用实现&#xff0c;即各微服务通过nacos或eureka服务器完成服务的注册&#xff0c;并从nacos中拉取配置实现热更新。当某个服务接口需要调用其他服务时&#xff0c;通过feign定义接口&#xff0c;并通过注解配置服务名…

C# ConcurrentQueue 使用详解

总目录 前言 在C#多线程编程中&#xff0c;数据共享如同走钢丝——稍有不慎就会引发竞态条件&#xff08;Race Condition&#xff09;或死锁。传统Queue<T>在并发场景下需要手动加锁&#xff0c;而ConcurrentQueue<T>作为.NET Framework 4.0 引入的线程安全集合&a…

在Vue项目中使用three.js在前端页面展示PLY文件或STL文件

前言&#xff1a;这是一个3d打印局域网管理系统的需求 一、安装three.js three.js官网&#xff1a;https://threejs.org/docs/#manual/en/introduction/Installation 我用的是yarn,官网用的是npm 二、使用three.js 1.在script部分导入three.js import * as THREE from thr…

DeepSeek 助力 Vue 开发:打造丝滑的右键菜单(RightClickMenu)

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 Deep…

大数据学习(46) - Flink按键分区处理函数

&&大数据学习&& &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 承认自己的无知&#xff0c;乃是开启智慧的大门 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4dd;支持一下博主哦&#x1f91…

10分钟上手DeepSeek开发:SpringBoot + Vue2快速构建AI对话系统

作者&#xff1a;后端小肥肠 目录 1. 前言 为什么选择DeepSeek&#xff1f; 本文技术栈 2. 环境准备 2.1. 后端项目初始化 2.2. 前端项目初始化 3. 后端服务开发 3.1. 配置文件 3.2. 核心服务实现 4. 前端服务开发 4.1. 聊天组件ChatWindow.vue开发 5. 效果展示及源…

Transformer多头注意力并行计算原理与工业级实现:从数学推导到PyTorch工程优化

一、核心数学原理剖析 1.1 多头注意力矩阵分解 Q XW^Q ∈ R^{nd_k} K XW^K ∈ R^{nd_k} V XW^V ∈ R^{nd_v} 多头分解公式&#xff1a; head_i Attention(QW_i^Q, KW_i^K, VW_i^V) 其中 W_i^Q ∈ R^{d_kd_k/h}, W_i^K ∈ R^{d_kd_k/h}, W_i^V ∈ R^{d_vd_v/h} (h为头数…

通过监督微调提升多语言大语言模型性能

引言 澳鹏助力一家全球科技公司提升其大语言模型&#xff08;LLM&#xff09;的性能。通过提供结构化的人工反馈形式的大语言模型训练数据&#xff0c;让该模型在30多种语言、70多种方言中的表现得到优化。众包人员们进行多轮对话&#xff0c;并依据回复的相关性、连贯性、准确…

大数据开发治理平台~DataWorks(核心功能汇总)

目录 数据集成 功能概述 使用限制 功能相关补充说明 数据开发 功能概述 数据建模 功能概述 核心技术与架构 数据分析 功能概述 数据治理 数据地图 功能概述 数据质量 功能概述 数据治理资产 功能概述 使用限制 数据服务 功能概述 数据集成 DataWorks的数据…

用Nginx打造防盗链护盾

用Nginx打造防盗链护盾 一、你的网站正在"为他人做嫁衣"&#xff1f; 想象一下这个场景&#xff1a; 你精心拍摄的摄影作品、录制的课程视频、设计的原创素材&#xff0c;被其他网站直接盗用链接。 更气人的是——当用户在他们网站查看这些资源时&#xff0c;消耗的…

STM32 看门狗

目录 背景 独立看门狗&#xff08;IWDG&#xff09; 寄存器访问保护 窗口看门狗&#xff08;WWDG&#xff09; 程序 独立看门狗 设置独立看门狗程序 第一步、使能对独立看门狗寄存器的写操作 第二步、设置预分频和重装载值 第三步、喂狗 第四步、使能独立看门狗 喂狗…

Kubernetes的Ingress 资源是什么?

在Kubernetes中&#xff0c;Ingress资源是一种用于管理集群外部对内部服务访问的API对象&#xff0c;主要用于将不同的外部请求路由到集群内的不同服务&#xff0c;以下是关于它的详细介绍&#xff1a; 定义与作用 Ingress资源定义了从集群外部到内部服务的HTTP和HTTPS路由规…

vue3-03初学vue3中的配置项setup(Composition API (组合API组件中所用到的:数据、方法等,均要配置在setup中)

1.关于setup Vue3.0中一个新的配置项&#xff0c;值为一个函数.setup是所有Composition API (组合API)“表演的舞台”m组件中所用到的:数据、方法等等&#xff0c;均要配置在setup中。 2..setup函数使用 setup函数的两种返回值 1.若返回一个对象&#xff0c;则对象中的属性、…

【go语言规范】 使用函数式选项 Functional Options 模式处理可选配置

如何处理可选配置&#xff1f; Config Struct 方式 (config-struct/main.go) 这是最简单的方式&#xff0c;使用一个配置结构体&#xff1a; 定义了一个简单的 Config 结构体&#xff0c;包含 Port 字段创建服务器时直接传入配置对象优点&#xff1a;简单直接缺点&#xff1a…

leetcode 2585. 获得分数的方法数

题目如下 数据范围 莫要被困难的外衣骗了&#xff0c;本题就是有数量限制的完全背包问题。显然我们可以令 f(x,y)为当有x种题目时分数为y时的方法数 令某种题目的数量为k 那么方法数应该是 f(x,y) f(x - 1,y - k * (分值))其中(0 < k < 题目数量)通过代码 class So…

深入理解JavaScript中的异步编程与Promise

一、引言 在JavaScript的世界中&#xff0c;异步编程是一个核心概念&#xff0c;尤其是在处理网络请求、文件操作或任何可能阻塞主线程的任务时。本文将深入探讨JavaScript中的异步编程模型&#xff0c;特别是Promise对象的使用。 二、异步编程基础 2.1 什么是异步编程&…

VS Code 如何搭建C/C++开发环境

目录 1.VS Code是什么 2. VS Code的下载和安装 2.1 下载和安装 2.2.1 下载 2.2.2 安装 2.2 环境的介绍 2.3 安装中文插件 3. VS Code配置C/C开发环境 3.1 下载和配置MinGW-w64编译器套件 3.1.1 下载 3.1.2 配置 3.2 安装C/C插件 3.3 重启VSCode 4. 在VSCode上编写…

如何查询网站是否被百度蜘蛛收录?

一、使用site命令查询 这是最直接的方法。在百度搜索框中输入“site:你的网站域名”&#xff0c;例如“site:example.com”&#xff08;请将“example.com”替换为你实际的网站域名&#xff09;。如果搜索结果显示了你的网站页面&#xff0c;并且显示了收录的页面数量&#xf…