KingbaseES 处理 PL/SQL 运行时错误全解析:从异常捕获到异常处理的实践指南

KingbaseES 处理 PL/SQL 运行时错误全解析:从异常捕获到异常处理的实践指南

引言

在国产化数据库替代浪潮中,KingbaseES凭借其与 Oracle PL/SQL 高兼容度,成为金融、政务等关键行业数据库迁移的首选。然而在实际迁移过程中,开发者常遇到"相同的PL/SQL代码在Oracle运行正常,在KingbaseES却报错"的困惑。

在这里插入图片描述

本文通过实践,梳理KingbaseES异常处理机制,从语法差异到运行时错误的完整解决方案,共同构建高可靠的国产数据库应用。

No.文章地址(点击进入)
1电科金仓KingbaseES数据库解析:国产数据库的崛起与技术创新
2KingBase数据库迁移利器:KDTS工具深度解析与实战指南
3KingBase数据库迁移利器:KDTS工具 MySQL数据迁移到KingbaseES实战
4电科金仓KingbaseES V9数据库:国产数据库的自主创新与行业实践深度解析
5KingbaseES客户端工具Ksql使用全指南:从安装到高级操作
6Spring JDBC与KingbaseES深度集成:构建高性能国产数据库应用实战
7深度解析:基于 ODBC连接 KingbaseES 数据库的完整操作与实践
8Oracle与Kingbase深度兼容体验:从连接配置到性能优化全解析
9Python驱动Ksycopg2连接和使用Kingbase:国产数据库实战指南
10Go语言×Kingbase数据库极速打通:Gokb驱动三步实操,让国产数据库连接效率嘎嘎提升!
11金仓数据库KingbaseES实现MongoDB平滑迁移全攻略:从架构适配到性能调优的完整实践
12深度解析:通过ADO.NET驱动Kdbndp高效连接与操作Kingbase数据库
13PHP驱动Pdo_kdb连接Kingbase数据库全攻略:从零到实战的深度指南
14KingbaseES数据库操作指南(1):SQL语法从入门到精通
15KingbaseES数据库操作指南(2):SQL语法从入门到精通
16KingbaseES通过KDTS实现SQLServer至KingbaseES迁移深度实战指南
17KingbaseES权限隔离深度解析:从MySQL的遗憾到安全增强的革新之路
18深度解析KingbaseES数据库备份利器sys_dump:从参数到实战的全流程指南
19KingbaseES数据库——医疗领域的应用实践与深度探索
20KingbaseES赋能新能源电力交易——电力现货交易辅助决策系统国产化实践深度解析
21KingbaseES在政务领域的应用实践——武汉人社大数据平台“数字化服务新模式”
22KingbaseES在国家电网领域的深度应用与实践——国家电网新一代集控系统
23KingbaseES 面向应用程序的SQL开发深度实践指南
24KingbaseES 面向应用程序的SQL开发:从原理到实战的深度探索
25破局困境:Oracle迁移金仓KingbaseES数据库的深度实践
26破译JSON密码:KingbaseES全场景JSON数据处理实战指南
27国产数据库替代指南:SQL Server向KingbaseES平滑迁移

一、异常处理机制

异常(PL/SQL 运行时错误)可能来自设计错误、编码错误、硬件故障或其他来源。无法预先处理所有可能触发的异常,但可以编写异常处理程序,让程序在触发异常的情况下继续运行。

1.1 异常处理原理

KingbaseES三级异常处理架构

  • 语法解析:通过扩展的SQL解析器识别Oracle PL/SQL特有语法
  • 语义逻辑:将Oracle语义规则映射为KingbaseES执行逻辑
  • 函数映射:内置同名函数实现无缝替换

当执行到错误语句时,控制流会跳转到对应的EXCEPTION块。系统在异常条件列表中匹配当前触发的异常,若匹配成功则执行对应的HandlerStatements,否则异常会向外层传播直至被捕获或终止程序。

1.2 封闭块

异常处理程序运行后,控制权转移到封闭块的下一条语句。如果没有封闭块会出现下面的情况

如果异常处理程序在子程序中,则将控制权返回给调用者调用之后的语句处
如果异常处理程序位于匿名块中,则控制权转移到主机环境

如果在没有异常处理程序的 PL/SQL 块中触发异常,则异常会传播。也就是说,异常会在连续的封闭块中向上抛出,直到一个 PL/SQL 块有一个异常处理程序或没有封闭块为止,如果没有异常处理程序,那么 PL/SQL 会向调用者或主机环境返回一个未处理的异常,这将决定最终的返回结果

1.3 异常种类

KingbaseES异常的种类分为:

系统预定义异常

系统预定义异常是 PL/SQL 已命名的异常,这些异常都有一个错误代码,且会在系统运行出错时隐式(自动)触发。

用户自定义异常

可以在任何 PL/SQL 匿名块、子程序或包的声明部分中声明自己的异常。例如,可以声明一个名为 invalid_number 的异常标记一个无效数字。 用户自定义异常必须显式的触发。

异常差异


下面将详细讲解两种异常

1.4 异常处理程序的优点

使用异常处理程序进行异常处理使程序更易于编写和理解,并降低了未处理异常的可能性。

如果没有异常处理程序,则必须检查所有可能触发的异常,并处理它。但这样很容易忽略可能出现的异常,尤其是在无法立即检测到异常的情况下(例如,在计算运行之前使用了错误数据可能无法检测到)。异常处理代码可以分散在整个程序中。

使用异常处理程序,不需要预先知道每个可能触发的异常或它可能发生的位置。只需在可能发生错误的每个块中包含一个异常处理模块。在异常处理模块中,用户可以编写处理特定错误或未知错误的异常处理程序。如果块中的任何地方(包括子块内)发生错误,则异常处理程序都会捕获并处理它。错误处理代码则会被隔离在块的异常处理部分。

一个存储过程使用单个异常处理程序来处理预定义异常 NO_DATA_FOUND,该异常可以出现在两个 SELECT INTO 语句中的任何一个中。

如果多个语句使用相同的异常处理程序,并且用户想知道哪个语句触发了异常,则可以使用变量辅助定位。

如果用户可以确定需要处理哪个异常,就可以为特定异常设置一个异常处理程序。用户还可以通过将语句放入具有自己的异常处理程序的块中来检查单个语句中的异常。

二、系统预定义异常

针对许多比较常见的异常以及系统运行时会触发的异常, PL/SQL 内部为其预定义了一个名称。例如:除零错误,对应的预定义异常名称为 DIVISION_BY_ZERO。当错误发生时,系统隐式(自动)抛出该异常。

PL/SQL 预定义异常‘

在这里插入图片描述


预定义异常信息可通过数据库系统函数 SYS_GET_PREDEFINED_EXCEPTION_DETAIL 进行查询

2.1 匿名块中处理 DIVISION_BY_ZERO

set serverout on \set SQLTERM /DECLARE stock_price NUMBER :=9.73; net_earnings NUMBER :=0; pe_ratio NUMBER;BEGIN pe_ratio := stock_price / net_earnings;-- raises ZERO_DIVIDE exception DBMS_OUTPUT.PUT_LINE('Price/earnings ratio = '|| pe_ratio); EXCEPTION WHEN ZERO_DIVIDE THEN DBMS_OUTPUT.PUT_LINE('Company had zero earnings.'); pe_ratio :=NULL;END;/ \set SQLTERM ;

结果:

Company had zero earnings.

2.2 匿名块中避免 DIVISION_BY_ZERO

\set SQLTERM /DECLARE stock_price NUMBER :=9.73; net_earnings NUMBER :=0; pe_ratio NUMBER;BEGIN pe_ratio :=CASE net_earnings WHEN0THENNULLELSE stock_price / net_earnings END;END;/ \set SQLTERM ;

三、用户自定义异常

用户可以在任何 PL/SQL 块,函数、存储过程或者包中声明一个异常。

语法格式:

exception_name EXCEPTION ;

用户自定义异常必须被显式触发,有关异常触发的详细信息

用户自定义异常可以与一个错误码进行绑定,具体语法为:

PRAGMA EXCEPTION_INIT (exception, error_code);

其中 exception 是用户自定义的异常, error_code 是大于 -1000000 且小于 0 的整数,error_code 可以是系统预定义异常的错误码。

四、重新声明预定义的异常

建议不要重新声明系统预定义的异常,即声明用户定义的异常名称与系统预定义的异常名称同名

如果重新声明了系统预定义的异常,那么本地声明将覆盖STANDARD 包的全局声明。此时只能使用 STANDARD包名来限定全局异常名称,否则异常处理程序无法处理全局异常。

重新声明预定义异常:

DROPTABLEIFEXISTS t CASCADE;CREATETABLE t (c NUMBER(2,1));

在下面的块中,INSERT 语句隐式引发了 VALUE_ERROR 异常,异常处理程序捕获并处理了这个异常。

set serverout on \set SQLTERM /DECLARE default_number NUMBER :=0;BEGININSERTINTO t VALUES(TO_NUMBER('100.001','9G999')); EXCEPTION WHEN VALUE_ERROR THEN DBMS_OUTPUT.PUT_LINE('Substituting default value for invalid number.');INSERTINTO t VALUES(default_number);END;/ \set SQLTERM ;

结果:

Substituting defaultvaluefor invalid number.

以下块重新声明了预定义的异常VALUE_ERROR。当 INSERT 语句隐式触发预定义异常 VALUE_ERROR 时,异常处理程序不会处理它。

set serverout on \set SQLTERM /DECLARE default_number NUMBER :=0; value_error EXCEPTION;-- redeclare predefined exceptionBEGININSERTINTO t VALUES(TO_NUMBER('100.001','9G999')); EXCEPTION WHEN VALUE_ERROR THEN DBMS_OUTPUT.PUT_LINE('Substituting default value for invalid number.');INSERTINTO t VALUES(default_number);END;/ \set SQLTERM ;

结果:

ERROR: numeric field overflow DETAIL: A field withprecision2, scale 1 must round to an absolute value less than 10^1. CONTEXT: SQL statement "INSERT INTO t VALUES(TO_NUMBER('100.001', '9G999'))" PL/SQLfunction inline_code_block line 5 at SQL statement 

如果在异常处理程序中使用包名 STANDARD 限定异常名称,则上述块中的异常处理程序将处理预定义的异常 VALUE_ERROR:

set serverout on \set SQLTERM /DECLARE default_number NUMBER :=0; value_error EXCEPTION;-- redeclare predefined exceptionBEGININSERTINTO t VALUES(TO_NUMBER('100.001','9G999')); EXCEPTION WHEN STANDARD.VALUE_ERROR THEN DBMS_OUTPUT.PUT_LINE('Substituting default value for invalid number.');INSERTINTO t VALUES(default_number);END;/ \set SQLTERM ;

结果:

Substituting defaultvaluefor invalid number.

五、显式触发异常

要显式触发常,使用 RAISE 语句或 存储过程RAISE_APPLICATION_ERROR。

5.1 RAISE 语句

RAISE 语句可以显式的触发一个异常。在异常处理程序之外,RAISE 语句必须指定异常名称。如果在异常处理程序内部,且省略了异常名称,那么该 RAISE 语句将重新引发当前正在处理的异常。

语法格式:

RAISE [ exception ];

其中 exception 可以是已定义的用户自定义异常,也可以是系统预定义异常。

省略 exception 的 RAISE 子句仅可在异常处理模块中使用。

5.2 使用 RAISE 语句触发用户自定义的异常

存储过程声明了一个名为 past_due 的异常,使用 RAISE 语句显式触发它,并使用异常处理程序处理它。

声明、触发和处理用户定义的异常

\set SQLTERM /CREATEPROCEDURE account_status ( due_date DATE, today DATE) AUTHID DEFINERIS past_due EXCEPTION;-- declare exceptionBEGINIF due_date < today THEN RAISE past_due;-- explicitly raise exceptionENDIF; EXCEPTION WHEN past_due THEN-- handle exception RAISE NOTICE 'Account past due.';END;/ \set SQLTERM ;

调用存储过程:

\set SQLTERM /BEGIN account_status (TO_DATE('01-JUL-2010','DD-MON-YYYY'), TO_DATE('09-JUL-2010','DD-MON-YYYY'));END;/ \set SQLTERM ;

输出结果:

NOTICE: Account past due.

5.3 使用 RAISE 语句触发系统预定义的异常

系统预定义异常通常由系统运行时隐式触发,但也可以使用 RAISE 语句显式地触发它们。当一个预定义异常拥有对应的异常处理程序时,无论是显式触发还是隐式触发,都会触发异常处理程序对相应的异常进行处理。

存储过程不论显式或是隐式触发预定义异常 VALUE_ERROR,异常处理程序始终都会处理它。

触发系统预定义异常

DROPTABLEIFEXISTS t CASCADE;CREATETABLE t (c NUMBER(2,1)); \set SQLTERM /CREATEPROCEDURE p (n NUMBER) AUTHID DEFINERIS default_number NUMBER :=0;BEGINIF n <0THEN RAISE VALUE_ERROR;-- 显式触发ELSEINSERTINTO t VALUES(TO_NUMBER('100.001','9G999'));-- 隐式触发ENDIF; EXCEPTION WHEN VALUE_ERROR THEN RAISE NOTICE 'Substituting default value for invalid number.';INSERTINTO t VALUES(default_number);END;/ \set SQLTERM ;

调用存储过程:

\set SQLTERM /BEGIN p(-1);END;/ \set SQLTERM ;

输出结果:

NOTICE: Substituting defaultvaluefor invalid number.

再次调用存储过程:

\set SQLTERM /BEGIN p(1);END;/ \set SQLTERM ;

输出结果:

NOTICE: Substituting defaultvaluefor invalid number.

六、总结与展望

KingbaseES通过完善的异常处理机制,实现了从语法兼容到运行时行为的全面Oracle兼容。其三级异常处理架构、丰富的预定义异常、灵活的自定义异常能力,配合智能诊断工具,构建了完整的异常处理生态体系。

Read more

告别996:GitHub Copilot将我的开发效率提升300%的实战记录

告别996:GitHub Copilot将我的开发效率提升300%的实战记录

👋 大家好,欢迎来到我的技术博客! 📚 在这里,我会分享学习笔记、实战经验与技术思考,力求用简单的方式讲清楚复杂的问题。 🎯 本文将围绕AI这个话题展开,希望能为你带来一些启发或实用的参考。 🌱 无论你是刚入门的新手,还是正在进阶的开发者,希望你都能有所收获! 文章目录 * 告别996:GitHub Copilot将我的开发效率提升300%的实战记录 * 引言:从疲惫到高效 * 什么是GitHub Copilot?🤖 * 效率提升300%的核心场景 * 1. 快速生成样板代码 * 2. 自动编写单元测试 * 3. 智能调试与注释 * 集成Copilot到工作流 * 步骤1:设置合理的期望 * 步骤2:结合IDE使用 * 步骤3:代码审查与调整 * 高级用法:超越代码生成 * 数据库查询优化 * API接口设计 * 正则表达式助手 * 数据支撑:效率提升分析 * 避坑指南:常见问题与解决 * 1. 可能生成过时或不安全代码

By Ne0inhk
GTC2026前瞻(二)Agentic AI 与开源模型篇+(三)Physical AI 与机器人篇

GTC2026前瞻(二)Agentic AI 与开源模型篇+(三)Physical AI 与机器人篇

(二)Agentic AI 与开源模型篇 Agentic AI与开源模型:英伟达想定义的,不只是“更聪明的模型”,而是“能持续工作的数字劳动力” 如果说过去两年的大模型竞赛,核心问题还是“谁能生成更像人的答案”,那么到了 GTC 2026,问题已经明显变了。英伟达把 Agentic AI 直接列为大会四大核心主题之一,官方对这一主题的定义也很明确:重点不再是单轮问答,而是让 AI agent 能够推理、规划、检索并执行动作,最终把企业数据转化为可投入生产的“数字劳动力”。这说明,Agentic AI 在英伟达的语境里,已经不是一个前沿概念,而是下一阶段 AI 商业化的主战场。(NVIDIA) 一、GTC 2026真正的变化,是 AI 开始从“会回答”走向“会做事”

By Ne0inhk
GitHub CLI 安装指南

GitHub CLI 安装指南

GitHub CLI 是 GitHub 官方提供的命令行工具,可以帮助开发者方便地与 GitHub 平台进行交互,例如克隆仓库、提交代码、创建 Pull Request 等。 相比传统的 HTTPS 下载和操作,GitHub CLI 提供了以下显著的优势和特殊功能: GitHub CLI 的优势 1. 快速交互 GitHub 功能: * 不仅支持克隆仓库,还可以直接通过命令行创建 Issue、合并 Pull Request、管理 GitHub Actions 等操作。 * 节省了在 GitHub 网站和本地终端之间切换的时间。 2. 增强的身份验证支持: * 提供更安全的登录方式,支持 OAuth 和 SSH,不再需要手动输入用户名和密码。 * 支持 Personal

By Ne0inhk

CAM++智能家居:个性化语音助手的声纹唤醒机制

CAM++智能家居:个性化语音助手的声纹唤醒机制 1. 引言 随着智能家居设备的普及,用户对语音助手的安全性与个性化需求日益增长。传统语音唤醒系统往往依赖关键词检测(如“嘿 Siri”),但难以区分不同说话人,存在隐私泄露和误触发风险。为解决这一问题,基于声纹识别的个性化语音助手逐渐成为研究热点。 CAM++ 是由科哥开发的一套高性能说话人验证系统,其核心是 DAMO 团队提出的 CAM++(Context-Aware Masking++)模型,具备高精度、低延迟的特点,特别适用于资源受限的边缘设备。该系统不仅能判断两段语音是否来自同一说话人,还可提取 192 维的声纹特征向量(Embedding),为构建个性化的智能语音交互系统提供了坚实基础。 本文将深入解析 CAM++ 在智能家居场景下的应用逻辑,重点剖析其声纹唤醒机制的设计原理、工程实现路径以及优化策略,帮助开发者理解如何将其集成到实际产品中,打造真正“懂你”的语音助手。 2. 技术原理深度解析 2.1 声纹识别的本质与挑战 声纹识别(Speaker Verification)

By Ne0inhk