|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
在ORDERBY操作中,MySQL只有在排序条件不是一个查询条件表达式的情况下才使用索引。(虽然如此,在涉及多个数据表查询里,即使有索引可用,那些索引在加快ORDERBY方面也没什么作用)。存储历程|函数在PL/SQL开辟中调试存储历程和函数的一样平常性办法
择要:Oracle在PLSQL中供应的壮大特征使得数据库开辟职员能够在数据库端完乐成能充足庞大的义务,本文将分离Oracle供应的相干程序包(package)和一个十分优异的第三方开辟工具来先容在PLSQL中开辟及调试存储历程的办法,固然也合用于函数。
版权声明:本文能够恣意转载,转载时请务必以超链接情势标明文章原始出处和作者信息。
原文出处:http://www.aiview.com/notes/ora_using_proc.htm
作者:张洋Alex_doesAThotmail.com
最初更新:2003-8-2
目次筹办事情从一个最复杂的存储历程入手下手调试存储历程在存储过程当中写日记文件捕捉背例
Oracle在PLSQL中供应的壮大特征使得数据库开辟职员能够在数据库端完乐成能充足庞大的义务,本文将分离Oracle供应的相干程序包(package)和一个十分优异的第三方开辟工具来先容在PLSQL中开辟及调试存储历程的办法,固然也合用于函数。
本文所接纳的软件版本和情况:
服务器:Oracle8.1.2forSolaris8
PL/SQLDeveloper4.5
筹办事情
在入手下手之前,假定您已安装好了Oracle的数据库服务,并已创建数据库,设置好监听程序,以同意客户端举行毗连;同时您已具有了一台设置好当地Net服务名的开辟客户机,并已安装好PL/SQLDeveloper开辟工具的以上版本大概更新.
鄙人面的示例代码中,我们利用Oracle数据库默许供应的示例表scott.dept和scott.emp.建表的语句以下:
createtableSCOTT.DEPT
(
DEPTNONUMBER(2)notnull,
DNAMEVARCHAR2(14),
LOCVARCHAR2(13)
)
createtableSCOTT.EMP
(
EMPNONUMBER(4)notnull,
ENAMEVARCHAR2(10),
JOBVARCHAR2(9),
MGRNUMBER(4),
HIREDATEDATE,
SALNUMBER(7,2),
COMMNUMBER(7,2),
DEPTNONUMBER(2)
)
从一个最复杂的存储历程入手下手
我们如今必要编写一个存储历程,输出一个部门的编号,请求获得属于这个部门的一切员工信息,包含员工编号和姓名.员工的信息经由过程一个cursor前往给使用程序.
createorreplaceprocedureusp_getEmpByDept(
in_deptNoinnumber,
out_curEmpoutpkg_const.REF_CURSOR
)as
begin
opencurEmpfor
selectempno,
ename
fromscott.emp
wheredeptno=in_deptNo;
endusp_getEmpByDept;
下面我们界说了两个参数,个中第二个参数必要使用cursor前往员工信息,PLSQL中供应了REFCURSOR的数据范例,能够接纳两种体例举行界说,一种是强范例,一种是弱范例,前者在界说时指定cursor前往的数据范例,后者能够不指定,由数据库依据查询语句举行静态绑定.
在利用前必需起首利用TYPE关头字举行界说,我们把数据范例REF_CURSOR界说在自界说的程序包中:pkg_const
createorreplacepackagepkg_constas
typeREF_CURSORisrefcursor;
endpkg_const;
注重:这个包必要在创立下面的存储历程之前被编译,由于存储历程用到了包中界说的数据范例.
调试存储历程
利用PL/SQLDeveloper登录数据库,用户名scott,暗码默许为:tiger.将包和存储历程分离编译,然后在左边扫瞄器的procedure栏面前目今找到新建的存储历程,点击右键,选择"Test"/"测试",鄙人面添好必要输出的参数值,按快速键F8间接运转存储历程,实行完成以后,能够点开前往参数中间的按钮检察了局集.
假如存储历程外部语句较庞大,能够按F9进进存储历程举行跟踪调试.PL/SQLDeveloper供应与通用开辟工具相似的跟踪调试功效,分为step、stepover、stepout等多种体例,关于变量也可举行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的代码:
createorreplaceprocedureusp_getEmpByDept(
in_deptNoinnumber,
out_curEmpoutpkg_const.REF_CURSOR
)as
fiutl_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,******callingusp_getEmpByDeptbeginat||to_char(sysdate,hh24:mi:ssmm-dd-yyyy)||******);
utl_file.put_line(fi,INPUT:);
utl_file.put_line(fi,in_chID=>||in_chID);
endif;
opencurEmpfor
selectempno,
ename
fromscott.emp
wheredeptno=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_getEmpByDeptendat||to_char(sysdate,hh24:mi:ssmm-dd-yyyy)||******);
utl_file.new_line(fi,1);
utl_file.fflush(fi);
utl_file.fclose(fi);
endif;
exception
whenothersthen
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_getEmpByDeptendat||to_char(sysdate,hh24:mi:ssmm-dd-yyyy)||******);
utl_file.new_line(fi,1);
utl_file.fflush(fi);
utl_file.fclose(fi);
endif;
endif;
/*Raisetheexceptionforcaller.*/
raise_application_error(-20001,sqlcode|||||sqlerrm);
endusp_getEmpByDept;
在下面的代码中,我们又援用了两个新的常量:
DEBUG
LOG_PATH
分离界说了调试开关参数和文件路径参数,对此,我们必要修正我们后面界说的程序包:
createorreplacepackagepkg_constas
typeREF_CURSORisrefcursor;
DEBUGconstantboolean:=true;
LOG_PATHconstantvarchar2(256):=/usr/tmp/db;
endpkg_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,除非用户利用pragmaEXCEPTION_INIT将自界说背例绑定一个自界说的毛病号。当没有任何背例抛出时,sqlcode前往0。
上面是一个复杂的捕捉背例的例子:
declare
inumber(3);
begin
select100/0intoifromdual;
exception
whenzero_dividethen
...
end;
在下面的exception中我们利用others关头字捕捉一切未明白指定的背例,并举行纪录log处置,同时我们必需在做完这些处置以后,把背例再次抛出给挪用程序,挪用函数:
raise_application_error(),此函数向挪用程序前往一个用户自界说的毛病号码和毛病信息,第一个参数指定一个毛病号码,由用户自行界说,但必需限制在-20000至-20999之间,制止与Oracle外部界说exception的毛病号码抵触,第二个参数必要前往一个字符串,这里我们利用它前往我们下面捕捉的毛病号码和毛病形貌。
注重:经由过程raise_application_error()函数抛出的背例已不是入手下手在程序块外部捕捉的外部背例,而是由用户本人界说的。
Memory所有数据置于内存的存储引擎,拥有极高的插入,更新和查询效率。但是会占用和数据量成正比的内存空间。并且其内容会在Mysql重新启动时丢失 |
|