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

Oracle 第11章:异常处理

在 Oracle PL/SQL 中,异常处理是一个重要的概念,它用于管理程序执行过程中可能发生的错误或特殊情况。异常可以是系统预定义的,也可以是由用户自定义的。

异常类型与处理机制

PL/SQL 提供了两种类型的异常:

  1. 预定义异常:这些是由 Oracle 数据库自动引发的标准异常,如 NO_DATA_FOUND(没有找到数据),TOO_MANY_ROWS(返回多行数据),等等。
  2. 用户定义异常:开发者可以根据需要定义自己的异常来处理特定的情况。

异常处理的基本结构包括 EXCEPTION 块,在这个块中可以编写处理特定异常的代码。如果在 PL/SQL 块中抛出了异常,并且该异常没有被捕获,则会导致 PL/SQL 块的执行终止。

示例代码

下面是一个使用预定义异常 NO_DATA_FOUND 的简单示例:

DECLAREv_salary NUMBER;
BEGIN-- 尝试从员工表中获取员工的工资SELECT salary INTO v_salary FROM employees WHERE employee_id = 9999;-- 如果没有找到该员工,则会抛出 NO_DATA_FOUND 异常
EXCEPTIONWHEN NO_DATA_FOUND THENdbms_output.put_line('Employee not found.');
END;
/

在这个例子中,如果尝试查询一个不存在的员工记录,SELECT ... INTO 语句将无法成功执行,并触发 NO_DATA_FOUND 异常。我们通过 WHEN NO_DATA_FOUND 子句捕获这个异常,并输出一条信息。

用户定义异常

有时候,标准异常不足以描述某些特定错误情况,这时就需要定义自己的异常。定义自定义异常的方法如下:

DECLAREe_invalid_value EXCEPTION; -- 定义一个异常PRAGMA EXCEPTION_INIT(e_invalid_value, -20001); -- 给异常赋一个错误码
BEGIN-- 检查某个条件是否满足,如果不满足则抛出自定义异常IF salary < 0 THENRAISE e_invalid_value;END IF;
EXCEPTIONWHEN e_invalid_value THENdbms_output.put_line('Invalid value for salary.');
END;
/

在这个例子中,我们定义了一个名为 e_invalid_value 的自定义异常,并给它分配了一个 Oracle 错误码 -20001。当检查到工资值为负数时,我们就手动抛出这个异常。然后在 EXCEPTION 块中处理这个异常。

注意事项

  • 在实际应用中,应该尽量避免使用通用异常处理器(如 WHEN OTHERS),因为这可能会掩盖真正的错误源。
  • 使用异常处理时,要确保所有的可能异常都被正确处理,以防止程序崩溃。
  • 在定义自定义异常时,确保错误码的选择不会与 Oracle 预留的错误码冲突。

多个异常的处理

在复杂的业务逻辑中,可能需要处理多种不同的异常。在这种情况下,可以在 EXCEPTION 块中为每种异常提供特定的处理逻辑。下面是一个处理多个异常的例子:

DECLAREv_employee_id employees.employee_id%TYPE := 9999;v_salary      employees.salary%TYPE;
BEGIN-- 尝试从员工表中获取员工的工资SELECT salary INTO v_salary FROM employees WHERE employee_id = v_employee_id;-- 如果没有找到记录,或者返回了多条记录,都会抛出相应的异常
EXCEPTIONWHEN NO_DATA_FOUND THENdbms_output.put_line('No data found for employee ID ' || v_employee_id);WHEN TOO_MANY_ROWS THENdbms_output.put_line('Too many rows returned for employee ID ' || v_employee_id);WHEN OTHERS THEN-- 记录其他所有未预见的异常dbms_output.put_line('An unexpected error occurred: ' || SQLERRM);
END;
/

在这个例子中,我们增加了对 TOO_MANY_ROWS 异常的处理,以防查询返回多条记录的情况。同时,也保留了 WHEN OTHERS 子句来捕捉任何未预见的异常,并打印出错误信息。

使用自定义异常的最佳实践

当你创建自定义异常时,应该遵循以下最佳实践:

  1. 明确错误消息:为自定义异常提供明确的错误消息,以便于调试。
  2. 异常隔离:尽可能地隔离不同类型的异常,使得每种异常都有其特定的处理逻辑。
  3. 使用子类型:如果你有很多相似但又略有不同的异常,考虑定义一个基异常类型,并基于此类型定义子类型。

示例:自定义异常的使用

假设我们需要确保输入的数据符合一定的格式要求,我们可以定义一系列相关的异常:

DECLARETYPE validation_exception IS EXCEPTION;PRAGMA EXCEPTION_INIT(validation_exception, -20000);e_invalid_date validation_exception;e_invalid_name validation_exception;v_date DATE;v_name VARCHAR2(100);
BEGINv_date := TO_DATE('2024-02-30', 'YYYY-MM-DD'); -- 这里会抛出异常v_name := 'John Doe'; -- 假设这里有一个验证逻辑IF v_date > SYSDATE + 365 THENRAISE e_invalid_date;END IF;IF v_name NOT LIKE '%[A-Z][a-z]*%' THENRAISE e_invalid_name;END IF;-- 如果没有异常发生,继续执行后续逻辑...
EXCEPTIONWHEN e_invalid_date THENdbms_output.put_line('The date is invalid.');WHEN e_invalid_name THENdbms_output.put_line('The name is invalid.');WHEN OTHERS THENdbms_output.put_line('Unexpected error: ' || SQLERRM);
END;
/

在这个示例中,我们定义了两个自定义异常 e_invalid_datee_invalid_name,分别用于验证日期和名字的有效性。每个异常都有具体的检查逻辑,并且在 EXCEPTION 块中有对应的处理代码。

通过这种方式,你可以为应用程序添加更强大的错误检测和处理功能,同时提高代码的可读性和可维护性。

复杂应用场景中的异常处理

在更复杂的应用场景中,异常处理不仅限于简单的错误捕捉,还需要考虑异常传播、异常恢复等更高级的功能。例如,当一个事务中的一部分操作失败时,我们可能希望回滚整个事务,而不是仅仅处理单个操作的异常。

示例:事务处理与异常

假设我们正在实现一个银行转账的业务逻辑,涉及到从一个账户扣款并存入另一个账户。为了保证数据的一致性,我们需要在一个原子性的事务中完成这两个操作。如果其中一个操作失败,我们需要回滚整个事务。

DECLAREv_sender_account accounts.account_id%TYPE := '12345678';v_receiver_account accounts.account_id%TYPE := '87654321';v_amount NUMBER := 100;
BEGIN-- 开始一个新的事务SAVEPOINT start_of_transaction;-- 从发送者账户扣除金额UPDATE accounts SET balance = balance - v_amount WHERE account_id = v_sender_account RETURNING balance INTO v_sender_balance;-- 如果没有找到发送者账户或余额不足,回滚事务IF SQL%NOTFOUND OR v_sender_balance < 0 THENROLLBACK TO start_of_transaction;RAISE_APPLICATION_ERROR(-20001, 'Insufficient funds or account does not exist.');END IF;-- 向接收者账户增加金额UPDATE accounts SET balance = balance + v_amount WHERE account_id = v_receiver_account RETURNING balance INTO v_receiver_balance;-- 如果没有找到接收者账户,回滚事务IF SQL%NOTFOUND THENROLLBACK TO start_of_transaction;RAISE_APPLICATION_ERROR(-20002, 'Receiver account does not exist.');END IF;-- 如果一切顺利,提交事务COMMIT;
EXCEPTIONWHEN OTHERS THEN-- 回滚事务并记录错误信息ROLLBACK TO start_of_transaction;dbms_output.put_line('Transaction failed: ' || SQLERRM);
END;
/

在这个例子中,我们使用了 SAVEPOINT 来标记事务的开始点,并在每次更新操作之后检查是否存在异常。如果有异常发生,我们会回滚到事务的起点。只有当两个操作都成功时,才会提交事务。

异常处理与错误日志

除了处理异常本身外,记录详细的错误日志也是非常重要的一部分。当异常发生时,记录详细的错误信息可以帮助后续的故障排查和问题解决。

示例:记录错误日志

在 PL/SQL 中,可以使用 DBMS_OUTPUT.PUT_LINE 来输出简单的错误信息,但对于生产环境来说,通常会使用更专业的日志记录工具,如 DBMS_LOGMNR 或者其他日志框架来记录详细的错误信息。

BEGIN-- 尝试执行某项操作INSERT INTO transactions (id, amount) VALUES (1, 100);-- 如果插入失败,记录错误信息
EXCEPTIONWHEN DUP_VAL_ON_INDEX THENdbms_output.put_line('Duplicate value on index.');-- 在实际应用中,这里应该调用专门的日志记录过程-- LOG_ERROR('Duplicate value on index.', SQLERRM);
END;
/

在这个例子中,如果插入操作导致索引重复键异常,我们不仅输出了一个简单的错误信息,还可以记录详细的错误信息到日志文件中。

总结

通过上述讨论,我们可以看到异常处理不仅仅是简单的错误捕捉,而是涵盖了错误处理、事务管理和错误日志记录等多个方面。合理地设计和实现异常处理逻辑,可以使应用程序更加健壮和易于维护。在实际开发中,应该根据具体的应用场景和需求来选择合适的异常处理策略。

相关文章:

Oracle 第11章:异常处理

在 Oracle PL/SQL 中&#xff0c;异常处理是一个重要的概念&#xff0c;它用于管理程序执行过程中可能发生的错误或特殊情况。异常可以是系统预定义的&#xff0c;也可以是由用户自定义的。 异常类型与处理机制 PL/SQL 提供了两种类型的异常&#xff1a; 预定义异常&#xf…...

导航栏渐变色iOS

- (void)viewDidLoad {[super viewDidLoad];// 设置导航栏属性self.navigationBar.translucent NO;[self.navigationBar setTitleTextAttributes:{NSForegroundColorAttributeName : [UIColor whiteColor], NSFontAttributeName:[UIFont boldSystemFontOfSize:28]}];// 修复iO…...

mysql读写分离

一、proxysql实现mysql读写分离 二、mycat...

计算机的错误计算(一百四十二)

摘要 本节探讨 MATLAB中 附近数的正弦函数的计算精度问题。 例1. 已知 计算 与 直接贴图吧&#xff1a; 另外&#xff0c; 16位的正确值分别为 -0.3077518861551721e-8 与 0.4106402475009074e-3&#xff08;ISRealsoft 提供&#xff09;。 容易看出&#xff0c;MATLAB的…...

利用大模型辅助科研论文写作·第一期|论文写作·24-11-02

小罗碎碎念 从这期推文开始&#xff0c;开一个新的系列——如何利用大语言模型辅助论文写作。 我目前的推文主要都集中于分享已经发表的论文&#xff0c;前期背景积累到一定程度以后&#xff0c;我们要动手做实验然后写自己的论文。如果从头到尾&#xff0c;全都自己写&#xf…...

JavaScript。—关于语法基础的理解—

一、程序控制语句 JavaScript 提供了 if 、if else 和 switch 3种条件语句&#xff0c;条件语句也可以嵌套。 &#xff08;一&#xff09;、条件语句 1、单向判断 &#xff1a; if... &#xff08;1&#xff09;概述 < if >元素用于在判断该语句是否满足特定条…...

Tomcat 11 下载/安装 与基本使用

为什么要使用Tomcat&#xff1f; 使用Apache Tomcat的原因有很多&#xff0c;以下是一些主要的优点和特点&#xff1a; 1. 开源与免费 Tomcat是一个完全开源的项目&#xff0c;任何人都可以免费使用。它由Apache软件基金会维护&#xff0c;拥有一个活跃的社区&#xff0c;这…...

Linux系统时间服务——Chrony服务器

文章目录 Linux系统时间服务——Chrony服务器前言时间同步的重要性Linux系统的两种时钟系统时钟&#xff08;System Clock&#xff09;相关命令硬件时钟 (RTC - Real Time Clock)相关命令 Chrony介绍NTP Chronyc相关命令服务管理相关命令chronyc 基本命令时间校正和控制命令NTP…...

C# 接口(Interface)

C# 接口&#xff08;Interface&#xff09; 接口在C#中是一种非常重要的概念&#xff0c;它定义了一个约定&#xff0c;实现该接口的类必须遵循这个约定。接口可以包含方法、属性、事件和索引器&#xff0c;但不包含实现。这使得接口成为定义抽象行为的理想选择。在本文中&…...

《高频电子线路》—— 电容三端LC振荡器

文章内容来源于【中国大学MOOC 华中科技大学通信&#xff08;高频&#xff09;电子线路精品公开课】&#xff0c;此篇文章仅作为笔记分享。 电容三端LC振荡器 基本原理&#xff08;考毕兹电路&#xff09; 反馈电压从C2上取得&#xff0c;作为输入电压&#xff0c;形成正反馈&a…...

leetcode35.搜索插入位置

1&#xff09;题目描述&#xff1a; 2&#xff09;本题要求使用 时间复杂度O(log n)的算法&#xff0c;这里使用二分查找的方法&#xff0c;这道题本身不复杂&#xff0c;但是&#xff0c;在使用递归调用时&#xff0c;笔者经常把递归结束的边界搞错&#xff0c;这里给出几版代…...

Redis全系列学习基础篇之位图(bitmap)常用命令的解析

文章目录 描述常用命令及解析常用命令解析 应用场景统计不确定时间周期内用户登录情况思路分析实现 统计某一特定时间内活跃用户(登录一次即算活跃)的数量思路分析与实现 描述 bitmap是redis封装的用于针对位(bit)的操作,其特点是计算效率高&#xff0c;占用空间少,常被用来统计…...

Copilot功能

Copilot 1、简介&#xff1a;Copilot是由GitHub与OpenAI共同开发的一款AI编程助手&#xff0c;旨在帮助开发者提高工作效率&#xff0c;改善代码质量。 2、主要功能包括&#xff1a; 1.代码补全&#xff1a;Copilot可以在开发者编写代码时提供代码建议&#xff0c;包括函数、循…...

《GBDT 算法的原理推导》 11-13初始化模型 公式解析

本文是将文章《GBDT 算法的原理推导》中的公式单独拿出来做一个详细的解析&#xff0c;便于初学者更好的理解。 公式(11-13)是GBDT算法的第一步&#xff0c;它描述了如何初始化模型。公式如下&#xff1a; f 0 ( x ) arg ⁡ min ⁡ c ∑ i 1 N L ( y i , c ) f_0(x) \arg \m…...

# Easysearch 与 LLM 融合打造高效智能问答系统

LangChain通过提供统一的抽象层和丰富的工具&#xff0c;极大地简化了LLM应用程序的开发过程&#xff0c;使得开发者能够更加专注于业务逻辑。RAG技术则通过索引和检索生成两步流程&#xff0c;利用最新数据或私有数据作为背景信息来增强大模型的推理能力。然而&#xff0c;对于…...

本地可以插入表记录,生产不能插入表记录

先说解决方案&#xff1a; 切面没有注入容器&#xff0c;在切面这加上Component详情&#xff1a; 大致是这样一个方法&#xff0c;本地运行会插入数据到sys_log表&#xff0c;但部署到服务器上就不会插入&#xff0c;而服务部署三年多了&#xff0c;一个表一直是空的居然没人…...

11.Three.js使用indexeddb前端缓存模型优化前端加载效率

11.Three.js使用indexeddb前端缓存模型优化前端加载效率 1.简述 在使用Three.js做数字孪生应用场景时&#xff0c;我们常常需要用到大量模型或数据。在访问我们的数字孪生应用时&#xff0c;每次刷新都需要从web端进行请求大量的模型数据或其他渲染数据等等&#xff0c;会极大…...

功能测试:方法、流程与工具介绍

功能测试是对产品的各功能进行验证的一种测试方法&#xff0c;旨在确保软件以期望的方式运行并满足设计需求。以下是对功能测试的详细解释&#xff1a; 一、定义与目的 定义&#xff1a;功能测试&#xff08;Functional Testing&#xff09;&#xff0c;也称为行为测试&#…...

【Orange Pi 5 Linux 5.x 内核编程】-设备驱动中的sysfs

设备驱动中的sysfs 文章目录 设备驱动中的sysfs1、sysfs介绍2、内核对象(kobject)介绍3、设备驱动中的SysFS31 在/sys中创建目录3.2 创建sysfs文件3.2.1 创建属性3.2.2 创建sysfs文件4、驱动程序实现5、驱动验证1、sysfs介绍 sysfs是内核导出的虚拟文件系统,类似于/proc。sys…...

微信小程序-全局数据共享/页面间通信

一.全局数据共享 声明全局的变量&#xff0c;在app.js文件里 App({//全局共享的数据globalData:{token:},//设置全局数据setToken(token){this.globalData.tokentoken}})使用 getApp() 获取全局App实例 //返回全局唯一的APP实例 const appInstancegetApp()Page({login(){con…...

Docker 离线安装指南

参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性&#xff0c;不同版本的Docker对内核版本有不同要求。例如&#xff0c;Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本&#xff0c;Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查

在对接支付宝API的时候&#xff0c;遇到了一些问题&#xff0c;记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略

本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装&#xff1b;只需暴露 19530&#xff08;gRPC&#xff09;与 9091&#xff08;HTTP/WebUI&#xff09;两个端口&#xff0c;即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

《通信之道——从微积分到 5G》读书总结

第1章 绪 论 1.1 这是一本什么样的书 通信技术&#xff0c;说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号&#xff08;调制&#xff09; 把信息从信号中抽取出来&am…...

srs linux

下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935&#xff0c;SRS管理页面端口是8080&#xff0c;可…...

python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)

更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...

鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/

使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题&#xff1a;docker pull 失败 网络不同&#xff0c;需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计

随着大语言模型&#xff08;LLM&#xff09;参数规模的增长&#xff0c;推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长&#xff0c;而KV缓存的内存消耗可能高达数十GB&#xff08;例如Llama2-7B处理100K token时需50GB内存&a…...

学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”

2025年#高考 将在近日拉开帷幕&#xff0c;#AI 监考一度冲上热搜。当AI深度融入高考&#xff0c;#时间同步 不再是辅助功能&#xff0c;而是决定AI监考系统成败的“生命线”。 AI亮相2025高考&#xff0c;40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕&#xff0c;江西、…...

Spring是如何解决Bean的循环依赖:三级缓存机制

1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间‌互相持有对方引用‌,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...