admin 管理员组文章数量: 887062
2024年1月16日发(作者:log4j2 lookup)
Oracle PL/SQL相关技术整理
Oracle PL/SQL
相关技术整理
作 者:
时 间:2009-9-23
(不断更新完善中)
第1页/共18页
Oracle PL/SQL相关技术整理
目录
1
2
概述 ................................................................................................................................... 3
PL/SQL常用开发技巧 ................................................................................................... 3
2.1 异常处理和日志 ................................................................................................... 3
2.2 使用动态SQL ...................................................................................................... 5
2.3 使用动态CURSOR ............................................................................................. 7
2.4 Oracle 分析函数的使用 ..................................................................................... 9
2.5 使用PL/SQL开发基于EBS的HTML格式的报表 ..................................... 11
2.6 使用PL/SQL输出XML格式的数据 ............................................................. 12
注册步骤 ......................................................................................................................... 16
3.1 注册 17
3.2 注册Concurrent Program ............................................................................... 17
3.3 分配Request Group ......................................................................................... 18
3
第2页/共18页
Oracle PL/SQL相关技术整理
1 概述
PL/SQL是Oracle专有的SQL扩展语言,应用在Oracle数据库系统。PL/SQL 不是一个独立的产品,他是一个整合到ORACLE服务器和ORACLE工具中的技术,可以把PL/SQL看作ORACLE服务器内的一个引擎,SQL语句执行者处理单个的SQL语句,PL/SQL引擎处理PL/SQL程序块。当PL/SQL程序块在PL/SQL引擎处理时,ORACLE服务器中的SQL语句执行器处理PL/SQL程序块中的SQL语句。PL/SQL具有高性能、易使用、无缝地与SQL结合,以及强壮性等多项优点。
Oracle 数据库11g的新特性下PL/SQL的高效使用:
复合触发器(compound trigger)
触发器中的按序执行
Loop中CONTINUE的使用
创建无效触发器(Disabled Trigger)
在非DML语句中使用序列(sequence)
动态游标和 REF CURSOR 的可交换性
PLSQL_Warning
只读表(read-only table)
2 PL/SQL常用开发技巧
2.1 异常处理和日志
由于设计的不足,编码的失误,硬件的错误或者其他的一些原因,程序在运行的过程中会出现一些错误,因此异常处理和日志就变得很重要。通过对一些特定异常的处理,可以提高程序的稳定性和可持续性。
PL/SQL通过EXCEPTION来处理异常,不需要专门为监控异常编写大量的代码。
使用PL/SQL内置的标准Exception
PL/SQL提前定义好了很多内置的Exception供大家使用,在STANDARD程序包中可以查到。下面用到的三个Exception是在编程过程中最经常使用的异常处理。
Begin
Select a,b
Into :variable
From table
Where xxxxxx;
Exception
when no_data_found then -- 获取‘没有找到数据’这个错误
第3页/共18页
Oracle PL/SQL相关技术整理
fnd__line(‘No_Data_Found Error!’);
when too_many_rows then -- 获取‘存在多行记录’这个错误
fnd__line(‘Too_Many_Rows Error!’);
when others then -- 获取前面没有监控的所有其他错误
fnd__line(‘Other Error!’);
End;
下图中是一些标准的exception以及它们对应的Oracle错误编码和SQLCODE得值。
使用自定义的异常处理(user-defined exception)
除了系统提供的标准exception,根据实际需求我们也可以自定义exception来使用。自定义的Exception需要注意两点,一是必须在Declare段申明,二是在处理异常的时候,必须显性的使用Raise来获取异常。
下面是一个例子:
DECLARE
out_of_balance EXCEPTION;
BEGIN
...
BEGIN ---------- 子程序块开始
...
IF ... THEN
RAISE out_of_balance; -- 申报异常
END IF;
EXCEPTION
WHEN out_of_balance THEN
-- 处理异常错误
RAISE; -- 重新申报本次的异常给外层程序块
...
第4页/共18页
Oracle PL/SQL相关技术整理
END; ------------ 子程序块结束
EXCEPTION
WHEN out_of_balance THEN
-- 用另外的方式重新处理异常
Raise_application_error(20010,’out of balances’);
...
When others then
-- 处理程序可能存在的其他异常
…
END;
在异常处理中记录日志
在程序中处理异常是一个很好的编程习惯,而记录日志更是一种有效的编程方法。它在程序调试过程中特别重要,也利于错误原因的分析和程序的改进。
在PL/SQL程序中,可通过fnd__line(fnd_,’xxxxx’)来记录日志。在SQL PLUS中可通过dbms__line(‘xxxxx’)来记录。
2.2 使用动态SQL
PL/SQL块中我们使用的SQL分为:静态SQL语句和动态SQL语句。所谓静态SQL指在PL/SQL块中使用的SQL语句在编译时是明确的,执行的是确定对象。而动态SQL是指在PL/SQL块编译时SQL语句是不确定的,如根据用户输入的参数的不同而执行不同的操作。编译程序对动态语句部分不进行处理,只是在程序运行时动态地创建语句、对语句进行语法分析并执行该语句。
Oracle中动态SQL可以通过本地动态SQL来执行,也可以通过DBMS_SQL包来执行。
使用本地动态SQL
执行DDL语句
str_sql:=’create
table ’||table_name||’(’||field1||’ ’||datatype1||’,’||field2||’ ’||datatype2||’)’;
execute immediate str_sql; --动态执行DDL语句
执行DML语句
str_sql:=’insert into dinya_test values(:1,:2)’;
execute immediate str_sql using id,name; --动态执行插入操作,id和name为参数, using子句,按顺序将输入的值绑定到变量
执行带输出的DML语句
v_string:=’select count(*) from table_name a where =:id’;
execute immediate v_string into v_count using p_id;
使用DBMS_SQL包
使用DBMS_SQL包实现动态SQL的步骤如下:
A、先将要执行的SQL语句或一个语句块放到一个字符串变量中。
第5页/共18页
Oracle PL/SQL相关技术整理
B、使用DBMS_SQL包的parse过程来分析该字符串。
C、使用DBMS_SQL包的bind_variable过程来绑定变量。
D、使用DBMS_SQL包的execute函数来执行语句。
下面是详细的例子:
执行DDL语句
create or replace procedure proc_dbms_sql
( table_name in varchar2, --表名
field_name1 in varchar2, --字段名
datatype1 in varchar2, --字段类型
field_name2 in varchar2, --字段名
datatype2 in varchar2 --字段类型
) as
v_cursor number; --定义光标
v_string varchar2(200); --定义字符串变量
v_row number; --行数
begin
v_cursor:=dbms__cursor; --为处理打开光标
v_string:=’create table ’||table_name||’(’||field_name1||’ ’||datatype1||’,’||field_name2||’ ’||datatype2||’)’;
dbms_(v_cursor,v_string,dbms_); --分析语句
v_row:=dbms_e(v_cursor); --执行语句
dbms__cursor(v_cursor); --关闭光标
exception
when others then
dbms__cursor(v_cursor); --关闭光标
raise;
end;
执行DML语句
第6页/共18页
Oracle PL/SQL相关技术整理
create or replace procedure proc_dbms_sql_update
( id number,
name varchar2
)as
v_cursor number; --定义光标
v_string varchar2(200); --字符串变量
v_row number; --行数
begin
v_cursor:=dbms__cursor; --为处理打开光标
v_string:=’update dinya_test2 a set =:p_name where =:p_id’;
dbms_(v_cursor,v_string,dbms_); --分析语句
dbms__variable(v_cursor,’:p_name’,name); --绑定变量
dbms__variable(v_cursor,’:p_id’,id); --绑定变量
v_row:=dbms_e(v_cursor); --执行动态SQL
dbms__cursor(v_cursor); --关闭光标
exception
when others then
dbms__cursor(v_cursor); --关闭光标
raise;
end;
2.3 使用动态CURSOR
动态CURSOR,也就是REF CURSOR,它可以分为两类,一为强类型(限制),规定了返回的类型,还有一类为弱类型(非限制),不规定返回类型,可以获取任何结果集。
动态CURSOR的特点:
PL/SQL静态光标不能返回到客户端,只有PL/SQL才能利用它。ref光标能
够被返回到客户端,这就是从Oracle的存储过程返回结果集的方式。
PL/SQL静态光标可以是全局的,而ref光标则不是。 也就是说,不能在包
说明或包体中的过程或函数之外定义ref光标。 只能在定义ref光标的过程中处理它,或返回到客户端应用程序。
使用静态光标--通过静态SQL(但不用ref光标)--比使用ref光标效率高,而
ref光标的使用仅限于这几种情况:把结果集返回给客户端;在多个子例程之间共享光标;没有其他有效的方法来达到你的目标时,则使用ref光标,正如必须用动态SQL时那样;
注意:在写程序的过程中,应首先考虑使用静态CURSOR,只有绝对必须使用ref光标时才使用ref光标,使用静态游标时建议尽量使用隐式游标,避免编写附加的游标控制代码(声明,打开,获取,关闭),也不需要声明变量来保存从游标中获取的数据。
第7页/共18页
Oracle PL/SQL相关技术整理
弱类型的REF CURSOR
Declare
type rc is ref cursor;
cursor c is select * from dual;
l_cursor rc;
begin
if (to_char(sysdate,'dd') = 30) then
-- ref cursor with dynamic sql
open l_cursor for 'select * from emp';
elsif (to_char(sysdate,'dd') = 29) then
-- ref cursor with static sql
open l_cursor for select * from dept;
else
-- with ref cursor with static sql
open l_cursor for select * from dual;
end if;
-- the "normal" static cursor
open c;
end;
从上面的例子中可以明细看到cursor C是个静态Cursor,l_cursor则为动态cursor,它可以是任何结果集。
强类型的REF CURSOR
declare
type gsm_rec is record(
gsmno varchar2(11),
status varchar2(1),
price number(8,2));
my_rec gsm_rec;
type app_ref_cur_type is ref cursor /*return gsm_rec可加可不加,不影响执行结果*/;
my_cur app_ref_cur_type;
begin
open my_cur for select gsmno,status,price from gsm_resource where
store_id='.01';
fetch my_cur into my_rec;
while my_cur%found loop
dbms__line(my_||'#'||my_||'#'||my_);
fetch my_cur into my_rec;
end loop;
close my_cur;
end;
第8页/共18页
Oracle PL/SQL相关技术整理
2.4 Oracle 分析函数的使用
分析函数为我们分析数据提供了一种简单高效的处理方式。在分析函数出现以前,我们必须使用自联查询,子查询或者内联视图,甚至复杂的存储过程实现的语句,现在只要一条简单的SQL语句就可以实现了,而且在执行效率方面也有相当大的提高。
下面是几种常用的分析函数:
自动汇总函数:Rollup,Cube
ROLLUP是GROUP BY子句的扩展,它是为每一个分组返回一条合计记录,并为全部分组返回总计。
select division_id, SUM(salary) from employees2
group by ROLLUP(division_id);
CUBE子句也是对GROUP BY子句进行扩展,返回CUBE中所有列组合的小计信息,同时在最后显示总计信息。CUBE的使用与ROLLUP基本相同,但CUBE的合计更加详细,它能够显示次分组字段的合计信息
select division_id,job_id,SUM(salary) from employees2
group by CUBE(division_id,job_id)
order by division_id;);
GROUPING()函数与ROLLUP、CUBE的结合使用:GROUPING()可接受一个列值,当列值为空时,函数返回1;如果列值非空,则返回0。
select
DECODE(GROUPING(division_id),1,'All divisions',division_id)AS div,
division_id,SUM(salary)
from employees2
group by ROLLUP(division_id);
rank 函数:rank, dense_rank, row_number
rank:排序。rank如果出现两个相同的排名,那么后面的数据就会直接跳过这个排名,就如考试排名次的时候并列2个第一名之后 是第3名。
第9页/共18页
Oracle PL/SQL相关技术整理
例子:下例中计算每个员工按部门分区再按薪水排序,注意薪水相同的时候序号一样,后面的序号跳过。
SELECT
ment_id , _name, ,
RANK() OVER (PARTITION BY ment_id ORDER BY ) as drank
FROM employees e, departments d
WHERE ment_id = ment_id
AND ment_id IN ('60', '90');
dense_rank:跟rank一样也是排序,区别就是就算出现相同的排名,后面的排名也不会被跳过。
例子:下例中计算每个员工按部门分区再按薪水排序,依次出现的序列号(注意与RANK函数的区别)
SELECT
ment_id , _name, ,
DENSE_RANK() OVER (PARTITION BY ment_id ORDER BY ) as drank
FROM employees e, departments d
WHERE ment_id = ment_id
AND ment_id IN ('60', '90');
row_number:row_number哪怕是两个数据完全相同,排名也按照行号排序。没有重复值。
例子:下例返回每个员工再在每个部门中按员工号排序后的顺序号
SELECT
department_id, last_name, employee_id,
ROW_NUMBER() OVER (PARTITION BY department_id ORDER BY employee_id) AS emp_id
FROM employees
WHERE department_id < 50;
lag, lead函数
Lag:可以访问结果集中的其它行而不用进行自连接。它允许去处理游标,就好像游标是一个数组一样。可以访问组中当前行之前的行。
例子:下面的例子中列prev_sal返回按hire_date排序的前1行的salary值
SELECT
last_name, hire_date, salary,
LAG(salary, 1, 0) OVER (ORDER BY hire_date) AS prev_sal
FROM employees
WHERE job_id = 'PU_CLERK';
Lead:lead与lag刚好相反,可以访问组中当前行之后的行。
第10页/共18页
Oracle PL/SQL相关技术整理
例子:下面的例子中每行的"NextHired"返回按hire_date排序的下一行的hire_date值
SELECT last_name, hire_date,
LEAD(hire_date, 1) OVER (ORDER BY hire_date) AS "NextHired"
FROM employees
WHERE department_id = 30;
2.5 使用PL/SQL开发基于EBS的HTML格式的报表
使用PL/SQL开发HTML格式的报表并不复杂,可以通过下面2种方式实现:
使用fnd__line
Fnd_file是EBS自带的函数包,可以实现日志和并发请求结果的输出,fnd__line可以实现按行输出信息,并自动换行。
写入输出文件:
fnd__line(fnd_, ’
写入日志文件:
Fnd__line(fnd_, ’
使用htp.p
Htp.p是Oracle数据库自带的函数包,专门针对HTML进行操作,通过该过程可以输出结果。
Htp.p(’
在有中文字输出的HTML格式报表中,要想正确显示中文字符,最好在输出HTML标记的时候设置字符集为UTF8.
fnd__line(fnd_,
'')
定义并发程序的时候,将输出格式定义为HTML.
第11页/共18页
Oracle PL/SQL相关技术整理
2.6 使用PL/SQL输出XML格式的数据
随着BI Publisher越来越被广泛的使用, 利用PL/SQL输出XML数据源也越来越多的被用到。Oracle 10g中有两个包,专门用来处理XML格式,它们是dbms_xmlgen 和 dbms_xmlstore。
dbms_xmlgen:用来输出XML格式的数据
常用功能:
dbms_text('select * from xmldemo'); 处理SQL
dbms_(xmlhdl); 输出XML格式
getnumrowsprocessed(xml handle):=getxml所处理的实际行数
dbms_Rows(xmlhdl,10):=允许处理最大行数
dbms_settag(xmlhdl,'Packet'):=重置行集标签rowset
dbms_tag(xmlhdl,'Record'):=重置行标签row
dbms_lhandling(xmlhdl,2):=列空值如何表示,如:
用一个例子来说明用法:
第12页/共18页
Oracle PL/SQL相关技术整理
1.创建临时表,写入两条数据:
create table xmldemo (
a number,
b varchar2(10)
);
insert into xmldemo values (10,'first line');
insert into xmldemo values (20,'line 2');
commit;
2.使用dbms_xmlgen生成数据表的xml格式
declare
xmlhdl dbms_e;
line varchar2(200);
xmltext varchar2(32767);
begin
-- create ctxhandle
xmlhdl := dbms_text('select * from xmldemo');
-- generate xml format data into clob
xmltext := dbms_(xmlhdl);
-- display the xml content
loop
exit when xmltext is null;
line := substr(xmltext,1,instr(xmltext,chr(10))-1);
dbms__line(line);
xmltext := substr(xmltext,instr(xmltext,chr(10))+1);
end loop;
-- close ctxhandle
dbms_ontext(xmlhdl);
end;
输出结果:
first line
line 2
第13页/共18页
Oracle PL/SQL相关技术整理
dbms_xmlstore:用来增加,修改或者删除XML文件中的数据
新增数据的例子:
Declare
l_sales_emp xmltype;
l_ctx dbms_e;
l_rows pls_integer;
begin
-- get all the sales employees into an xml document
select xmlelement("ROWSET",
xmlagg(
xmlelement("ROW",
xmlforest(,,,,
te,,,)
)
)
)
into l_sales_emp
from emp e, dept d
where =
and ='SALES';
-- setup our dbms_xmlstore context
l_ctx := dbms_text('SALES_EMP');
l_rows := dbms_xml(
L_ctx, l_sales_bVal());
-- how many rows were inserted?
dbms__line(l_rows || ' rows inserted into SALES_EMP.');
-- clean up
dbms_ontext(l_ctx);
end;
更改数据的例子:
第14页/共18页
Oracle PL/SQL相关技术整理
declare
l_sales_emp xmltype;
l_ctx dbms_e;
l_rows pls_integer;
begin
-- simulate the updates to make
l_sales_emp := xmltype('
');
-- setup our dbms_xmlstore context
l_ctx := dbms_text('SALES_EMP');
-- setup the columns to be updated
dbms_pdatecolumnlist(l_ctx);
dbms_atecolumn(l_ctx, 'ENAME');
dbms_atecolumn(l_ctx, 'JOB');
dbms_atecolumn(l_ctx, 'MGR');
dbms_atecolumn(l_ctx, 'SAL');
-- setup the key columns to update by
dbms_column(l_ctx, 'EMPNO');
-- perform the update
l_rows := dbms_xml(l_ctx, l_sales_bVal());
-- how many rows were updated?
dbms__line(l_rows || ' rows updated in SALES_EMP.');
-- clean up
dbms_ontext(l_ctx);
第15页/共18页
Oracle PL/SQL相关技术整理
删除数据的例子:
declare
l_sales_emp xmltype;
l_ctx dbms_e;
l_rows pls_integer;
begin
-- simulate the updates to make
l_sales_emp := xmltype('
');
-- setup our dbms_xmlstore context
l_ctx := dbms_text('SALES_EMP');
-- setup the key column to delete by
dbms_column(l_ctx, 'EMPNO');
-- perform the delete
l_rows := dbms_xml(l_ctx, l_sales_bVal());
-- how many rows were deleted?
dbms__line(l_rows || ' rows deleted fm SALES_EMP.');
-- clean up
dbms_ontext(l_ctx);
end;
3 注册步骤
PL/SQL可作为程序包被储存在数据库里被其他程序(Report, Form, Unix shell,
discoverer, Java等)直接调用,也可以被注册在EBS系统里成为一个独立的并发请求。
注册步骤包括:
第16页/共18页
Oracle PL/SQL相关技术整理
3.1 注册Executable
N:Application Developer> Concurrent >Program >Executable
3.2 注册Concurrent Program
N:Application Developer> Concurrent>Program >Define
第17页/共18页
Oracle PL/SQL相关技术整理
3.3 分配Request Group
N:System Administrator> Security>Responsibility >Define
第18页/共18页
版权声明:本文标题:Oracle EBS PLSQL高级使用及相关技巧 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/jishu/1705354841h482350.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论