在PL/SQL 开发中调试存储过程和函数的一般性方法

PLSQL存储过程调试 1 如何进行调试 1.1 前言 在工作或者学习中,我们经常会遇到储存过程调用报错或者函数、触发器、包体等调用报错,如果完全依赖个人经验去排查问题,明显是不现实的,所幸PL/SQL Developer工具提供了强大的调试功能,完全可以与其他变成语言的IDE相媲美。后续将详细阐述如何使用PL/SQL Developer工具进行调试,以及调试过程中的常见操作问题解决办法。 1.2 安装PL/SQL Developer 软件版本:目前推荐版本为PL/SQL Developer 12,不推荐使用版本过低或者 阅读详情

在PL/SQL 开发中调试存储过程和函数的一般性方法

摘要: Oracle 在PLSQL中提供的强大特性使得数据库开发人员可以在数据库端完成功能足够复杂的任务, 本文将结合Oracle提供的相关程序包(package)以及一个非常优秀的第三方开发工具来介绍在PLSQL中开发及调试存储过程的方法,当然也适用于函数。

版权声明: 本文可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息。
原文出处: http://www.aiview.com/notes/ora_using_proc.htm
作者: 张洋 Alex_doesAThotmail.com
最后更新: 2003-8-2


 目录
  1. 准备工作
  2. 从一个最简单的存储过程开始
  3. 调试存储过程
  4. 在存储过程中写日志文件
  5. 捕获违例

 

Oracle 在PLSQL中提供的强大特性使得数据库开发人员可以在数据库端完成功能足够复杂的任务, 本文将结合Oracle提供的相关程序包(package)以及一个非常优秀的第三方开发工具来介绍在PLSQL中开发及调试存储过程的方法,当然也适用于函数。

本文所采用的软件版本和环境:
服务器: Oracle 8.1.2 for Solaris 8
PL/SQL Developer 4.5

准备工作

在开始之前, 假设您已经安装好了Oracle的数据库服务, 并已经建立数据库, 设置好监听程序, 以允许客户端进行连接; 同时您已经拥有了一台设置好本地Net服务名的开发客户机, 并已经安装好PL/SQL Developer开发工具的以上版本或者更新.

在下面的示例代码中,我们使用Oracle数据库默认提供的示例表 scott.dept 和 scott.emp. 建表的语句如下:

create table SCOTT.DEPT
(
DEPTNO NUMBER(2) not null,
DNAME VARCHAR2(14),
LOC VARCHAR2(13)
)

create table SCOTT.EMP
(
EMPNO NUMBER(4) not null,
ENAME VARCHAR2(10),
JOB VARCHAR2(9),
MGR NUMBER(4),
HIREDATE DATE,
SAL NUMBER(7,2),
COMM NUMBER(7,2),
DEPTNO NUMBER(2)
)

从一个最简单的存储过程开始

我们现在需要编写一个存储过程, 输入一个部门的编号, 要求取得属于这个部门的所有员工信息, 包括员工编号和姓名. 员工的信息通过一个cursor返回给应用程序.

create or replace procedure usp_getEmpByDept(
in_deptNo in number,
out_curEmp out pkg_const.REF_CURSOR 
) as
begin
open curEmp for 
select empno,
ename
from scott.emp
where deptno = in_deptNo;

end usp_getEmpByDept;

上面我们定义了两个参数, 其中第二个参数需要利用cursor返回员工信息, PLSQL中提供了REF CURSOR的数据类型, 可以采用两种方式进行定义, 一种是强类型,一种是弱类型, 前者在定义时指定cursor返回的数据类型, 后者可以不指定, 由数据库根据查询语句进行动态绑定.

在使用前必须首先使用TYPE关键字进行定义, 我们把数据类型REF_CURSOR定义在自定义的程序包中: pkg_const

create or replace package pkg_const as
type REF_CURSOR is ref cursor;

end pkg_const;

注意: 这个包需要在创建上面的存储过程之前被编译, 因为存储过程用到了包中定义的数据类型.

调试存储过程

使用PL/SQL Developer 登录数据库, 用户名scott, 密码默认为: tiger. 将包和存储过程分别编译, 然后在左侧浏览器的procedure栏目下找到新建的存储过程, 点击右键, 选择"Test"/"测试", 在下面添好需要输入的参数值, 按快捷键F8直接运行存储过程, 执行完成之后, 可以点开返回参数旁边的按钮查看结果集.

如果存储过程内部语句较复杂, 可以按F9进入存储过程进行跟踪调试. PL/SQL Developer提供与通用开发工具类似的跟踪调试功能, 分为step、step over、step out 等多种方式, 对于变量也可进行trace或者手动赋值。

在存储过程中写日志文件

以上方法可以在开发阶段对编写和调试存储过程提供最大限度的方便,但为了在系统测试或者生产环境中确认我们的代码是否正常工作时,就需要记录log。

PLSQL提供了一个UTL_FILE包,通过定义UTL_FILE包中的FILE_TYPE类型,可以获得一个文件句柄,通过此句柄可以实现一般的文件操作功能。但默认的数据库参数是不允许使用UTL_FILE包的,需要手动进行配置,使用GUI的管理工具或者手工编辑INIT.ORA文件,找到 "utl_file_dir" 参数,如果没有,则添加一行,修改成如下:

utl_file_dir='/usr/tmp'

或者

utl_file_dir=*

第一种方式限定了在UTL_FILE包中可以存取的目录,第二种方式则不进行限定。无论哪种方式,都要保证运行数据库实例的用户,一般是oracle,拥有此目录的存取权限,否则在使用包的过程中会报出错误信息。

注意等号左右不要留空格,可能会引起解析错误,导致设置无效。

下面在上面的存储过程中加入记录log的代码:

create or replace procedure usp_getEmpByDept(
in_deptNo in number,
out_curEmp out pkg_const.REF_CURSOR 
) as
fi utl_file.file_type;

begin
if( pkg_const.DEBUG ) then 
fi := utl_file.fopen( pkg_const.LOG_PATH, to_char( sysdate, 'yyyymmdd' ) || '.log', 'a' );
utl_file.put_line( fi, ' ****** calling usp_getEmpByDept begin at ' || to_char( sysdate, 'hh24:mi:ss mm-dd-yyyy' ) || ' ******' );
utl_file.put_line( fi, ' INPUT:' );
utl_file.put_line( fi, ' in_chID => ' || in_chID );
end if;

open curEmp for 
select empno,
ename
from scott.emp
where deptno = in_deptNo;

if( pkg_const.DEBUG ) then 
utl_file.put_line( fi, ' RETURN:' );
utl_file.put_line( fi, ' out_curEmp: unknown' );
utl_file.put_line( fi, ' ****** usp_getEmpByDept end at ' || to_char( sysdate, 'hh24:mi:ss mm-dd-yyyy' ) || ' ******' );
utl_file.new_line( fi, 1 );
utl_file.fflush( fi );
utl_file.fclose( fi );
end if;

exception
when others then

if( pkg_const.DEBUG ) then 
if( utl_file.is_open( fi )) then
utl_file.put_line( fi, ' ERROR:' );
utl_file.put_line( fi, ' sqlcode = ' || sqlcode );
utl_file.put_line( fi, ' sqlerrm = ' || sqlerrm );
utl_file.put_line( fi, ' ****** usp_getEmpByDept end at ' || to_char( sysdate, 'hh24:mi:ss mm-dd-yyyy' ) || ' ******' );
utl_file.new_line( fi, 1 );
utl_file.fflush( fi );
utl_file.fclose( fi );
end if;
end if;

/* Raise the exception for caller. */
raise_application_error( -20001, sqlcode || '|' || sqlerrm );

end usp_getEmpByDept;

在上面的代码中,我们又引用了两个新的常量:

DEBUG
LOG_PATH

分别定义了调试开关参数和文件路径参数,对此,我们需要修改我们前面定义的程序包:

create or replace package pkg_const as
type REF_CURSOR is ref cursor;

DEBUG constant boolean := true;
LOG_PATH constant varchar2(256) := '/usr/tmp/db';

end pkg_const;

在代码块的起始处,将输入参数的名称与值成对的记入log文件,在代码块的正常退出部分,将输出参数的名称和数值也成对的记录下来,如果程序非正常退出,则在exception 的处理部分,把错误代码及错误信息写入log文件。一般使用这些信息就可以较迅速的找出程序运行中出现的大部分错误。

注意:如果返回参数的类型是cursor,是无法在存储过程内部将返回的结果集一条一条写入log文件的,此时应当结合在调用程序中记录的log信息,下面具体分析一下上述代码:

fopen() 函数使用给定的路径和文件名,新建文件或者打开已有的文件,这取决于最后一个参数, 当使用'a'作为参数时,如果给定的文件不存在,则以此文件名新建文件,并以写'w'方式打开,返回一个文件句柄。

上面代码以天为单位建立日志文件,并且,不同存储过程之间共享log文件,这种方式的优点是可能通过查看log文件追溯出程序的调用顺序和逻辑。实际应用中,应根据不同的需求,具体分析,可以使用更复杂的log文件生成策略。

put_line() 函数用于写入字符到文件,并在字符串的结尾加入换行符,若不想换行,使用put()函数。

new_line() 函数用于生成指定数目的空行,上面对文件的修改写在一个缓冲区内,执行fflush() 将立即将buffer中的内容写入文件,当你希望在文件还未关闭之前就需要读取已经作出的改变时,调用此函数。

is_open() 函数用于判断一个文件句柄的状态,最后用完一定记得把打开的文件关闭,调用fclose() 函数,并且应把这个语句加入exception的处理中,防止过程非正常退出时留下未关闭的文件句柄。

捕获违例

在PLSQL中,你可以通过两个内建的函数sqlcode 和sqlerrm 来找出发生了哪类错误并且获得详细的message信息,在内部违例发生时,sqlcode返回从-1至-20000之间的一个错误号,但有一个例外,仅当内部违例no_data_found 发生时,才会返回一个正数 100。当用户自定义的违例发生时,sqlcode返回+1,除非用户使用 pragma EXCEPTION_INIT 将自定义违例绑定一个自定义的错误号。当没有任何违例抛出时,sqlcode返回0。

下面是一个简单的捕获违例的例子:

declare
i number(3);
begin
select 100/0 into i from dual;

exception
when zero_divide then
...
end;

在上面的exception 中我们使用others 关键字捕获所有未明确指定的违例,并进行记录log处理,同时我们必须在做完这些处理之后,把违例再次抛出给调用程序,调用函数:
raise_application_error(),此函数向调用程序返回一个用户自定义的错误号码和错误信息,第一个参数指定一个错误号码,由用户自行定义,但必须限定在-20000至-20999之间,避免与Oracle内部定义exception的错误号码冲突,第二个参数需要返回一个字符串,这里我们使用它返回我们上面捕获的错误号码和错误描述。

注意:通过raise_application_error()函数抛出的违例已经不是开始在程序块内部捕获的内部违例,而是由用户自己定义的。

oracle存储过程调试 本文主要介绍如何在PL/SQL Developer中如何调试oracle存储过程。1.    打开PL/SQL Developer如果在机器上安装了PL/SQL Developer的话,打开PL/SQL Developer界面输入用户名,密码host名字,这个跟在程序中web.config中配置的完全相同,点击确定 找到需要调试存储过程所在的包(Pac 阅读详情

相关推荐

PL/SQL存储过程调试全攻略与实战技巧

条件断点是一种基于表达式判断是否触发的断点类型,它允许开发者设定一个布尔条件,仅当该条件为真时才暂停程序执行。这种机制避免了在高频循环或频繁调用中反复手动跳过无关代码段的问题,显著提升了调试体验的流畅性与针对性。为突破的局限,建议建立专用日志表用于持久化记录。构建可重复的测试场景至关重要。建议创建独立的测试表空间或使用临时测试账户隔离数据影响。例如,建立简化版员工表用于调试:并预先定义各输入对应的期望输出:emp_id=101。

weixin_42601608的博客 1112

PLSQL 存储过程调用执行

1 什么是存储过程? ?用于在数据库中完成特定的操作或者任务。是一个PLSQL程序块,可以永久的保存在数据库中以供其他程序调用。 2 存储过程的参数模式 存储过程的参数特性: ?IN类型的参数?OUT类型的参数?IN-OUT类型的参数 值被?传递给子程序?返回给调用环境?传递给子程序 返回给调用环境 参数形式?常量?未初始化的变量?初始化的变量 使用

牧码人的专栏 2138

FOC控制必看:单/双/三电阻电流采样方案全对比(附NXP实战避坑指南)

本文深入对比了FOC控制中单电阻、双电阻三电阻电流采样方案的优劣与适用场景,重点剖析了采样时序、窗口与ADC转换的工程挑战。针对NXP平台,提供了解决采样窗口过窄的实战方案与配置指南,帮助工程师根据成本与性能需求做出最优选择,并规避常见设计陷阱。

n2o3p4的博客 381

pl-sql中关于函数test及存储过程中调用function函数

对于存储过程可以直接反键test 但是对于函数就要先在过程中调用,然后测试 例子: CREATE OR REPLACE PROCEDURE erik_test(str_code out varchar2) is a_strSql varchar2(256); ncount integer :=0; begin a_strSql := ' select count...

PowerKinging的专栏 617

PL/SQL开发调试存储过程函数一般性方法

<!--google_ad_client = "pub-2947489232296736";/* 728x15, 创建于 08-4-23MSDN */google_ad_slot = "3624277373";google_ad_width = 728;google_ad_height = 15;//--><script type="text/javascript"

zgqtxwd的专栏 674

PL/SQL存储过程

PL/SQL存储过程 一 创建并调用存储过程 1 建立存储过程ORACLE SERVER 上建立存储过程 可以被多个应用程序调用 可以向存储过程传递参数 也可以向存储过程传回参数 (1) 语法: CREATE [ OR REPLACE ] PROCEDURE Procedure_name [ (argment [ {IN | IN OU T }] Type, argment [ { IN | OUT | IN OUT } ] Type [ AUTHID DEFINER | CURRENT_USER

hcyxsh的博客 6935

PL/SQL调试存储过程

 如何调试oracle存储过程PL/SQL中为我们提供了调试存储过程的功能,可以帮助你完成存储过程的预编译与测试。 点击要调试存储过程,右键选择TEST 如果需要查看变量,当然调试都需要。在右键菜单中选择Add debug information. start debugger(F9)开始我们的测试,Run(Ctrl+R) 随时

1万+

PL/SQL Developer中调试oracle存储过程

唉,真土,以前用Toad,一直用dbms_output.put_line调试存储过程,只觉得不方便,用上PL/SQL Developer后,习惯性的还是用这个方法,人都是有惰性的。今天分析存储过程生成的数据,实在觉得不便,网上搜了一下,PL/SQL Developer中调试oracle存储过程方法,其实很简单。我知道学会使用PL/SQL Developer的调试功能,对于编写复杂的存储过程,包,funtion...非常有帮助,对执行存储过程形成的结果进行分析时也很有用处,学习之后,果然方便,现将相关步骤

驽马十驾 才定不舍 3万+

Oracle如何使用PL/SQL调试存储过程

Oracle如何使用PL/SQ...

我的博客 696

db2存储过程怎么调试_PL/SQL调试存储过程?看这篇就够了

概述虽然现在存储过程相对比较少用了,但是平时接触不可避免的要跟存储过程打交道,当需要自己写的时候总会碰到这或那的错误,这个时候一般要怎么调试呢?PL/SQL调试PL/SQL中提供了【调试存储过程】的功能,可以完成存储过程的预编译与测试。点击要调试存储过程,右键选择TEST如果需要查看变量,当然调试都需要。在右键菜单中选择Add debug information.start debugger(F...

weixin_29541589的博客 1207

VS2019调试查看变量_PL/SQL调试存储过程?看这篇就够了

概述虽然现在存储过程相对比较少用了,但是平时接触不可避免的要跟存储过程打交道,当需要自己写的时候总会碰到这或那的错误,这个时候一般要怎么调试呢?PL/SQL调试PL/SQL中提供了【调试存储过程】的功能,可以完成存储过程的预编译与测试。点击要调试存储过程,右键选择TEST如果需要查看变量,当然调试都需要。在右键菜单中选择Add debug information.start debugger(F...

weixin_39838829的博客 1285

如何执行存储过程_Oracle如何使用PL/SQL调试存储过程

调试过程对找到一个存过的bug或错误是非常重要的,Oracle作为一款强大的商业数据库,其上面的存过少则10几行,多则上千行,免不了bug的存在,存过上千行的话,找bug也很费力,通过调试可以大大减轻这种负担。工具/原料PL\SQLOracle方法/步骤首先在PL/SQL的左侧资源栏中展开Procedures项(图中位置1),然后再其上面的搜索框中(图中位置2)输入存过名称的关键词,按回...

weixin_36068140的博客 1388
上一篇: 建伍TH48A 双段手台操作手册中文版(全)
下一篇: 学习笔记-Linux 系统管理学习笔记(一)
alexdoes
博客等级 码龄23年 2粉丝 25原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值