Oracle中动态SQL详解

Oracle中动态SQL详解

1.静态SQLSQL与动态SQL

  Oracle编译PL/SQL程序两个:其一前期联编early binding),即SQL句在程序编译就已确定,大多数的编译情况属于这种类型;另外一是后期联编late binding),即SQL句只有在运行段才能建立,例如当查询条件户输,那OracleSQL引擎就无法在编译对该程序行确定,只能在用户输入一定的查询条件后才能提交SQL引擎理。通常,静SQL采用前一种编译方式,而动态SQL采用后一种编译方式。

  本文主要就动态SQL开发进讨论,并在最后出一些实际开发的技巧。

2动态SQL程序开发

  理解了动态SQL编译的原理,也就掌握了其基本的开发思想。动态SQL既然是一不确定SQL,那其行就有其相的特点。Oracle中提供了Execute immediate句来动态SQL法如下:

  
    
Excute immediate 动态SQL语句 using 绑定参数列表 returning into 输出参数列表;
对这 句作如下 明:

   1) 动态 SQL 是指 DDL 和不确定的 DML (即 参数的 DML

   2) 定参数列表 为输 入参数列表,即其 in 型,在运行 刻与 动态 SQL 句中的参数( 实际 上占位符,可以理解 函数里面的形式参数) 定。

   3) 出参数列表 为动态 SQL 行后返 回的参数列表。

   4) 由于 动态 SQL 是在运行 行确定的,所以相 于静 而言,其更多的会 失一些系 性能来 取其灵活性。

  了更好的 明其 开发 程,下面列 一个 例:

   数据 emp 表,其数据 如下:

ID

NAME

SALARY

100

Jacky

5600

101

Rose

3000

102

John

4500

要求:

  1表并入相的数据。

  2.根据特定ID可以查询到其姓名和薪水的信息。

  3.根据大于特定的薪水的查询工信息。

  根据前面的要求,可以分别创建三个程(均使用动态SQL)来实现

 程一:

  
    
create or replace procedure create_table as
begin
execute immediate '
create table emp(id number,
name varchar2(10),
salary number )
' ; -- 动态SQL为DDL语句
insert into emp
values ( 100 , ' jacky ' , 5600 );
insert into emp
values ( 101 , ' rose ' , 3000 );
insert into emp
values ( 102 , ' john ' , 4500 );
end create_table;

程二:

  
    
create or replace procedure find_info(p_id number ) as
v_name
varchar2 ( 10 );
v_salary
number ;
begin
execute immediate '
select name,salary from emp
where id=:1
'
using p_id
returning
into v_name,v_salary; -- 动态SQL为查询语句
dbms_output.put_line(v_name || ' 的收入为: ' || to_char(v_salary));
exception
when others then
dbms_output.put_line(
' 找不到相应数据 ' );
end find_info;
  程三:

  
    
create or replace procedure find_emp(p_salary number ) as
r_emp emp
% rowtype;
type c_type
is ref cursor ;
c1 c_type;
begin
open c1 for '
select * from emp
where salary >:1
'
using p_salary;
loop
fetch c1 into r_emp;
exit when c1 % notfound;
dbms_output.put_line(
' 薪水大于‘||to_char(p_salary)||’的员工为:‘);
dbms_output.put_line(
' ID为 ' to_char(r_emp)|| ' 其姓名为: ' ||r_emp.name);
end loop;
close c1;
end create_table;
注意:在 程二中的 动态 SQL 句使用了占位符 “:1“ ,其 它相当于函数的形式参数,使用 ,然后使用 using 句将 p_id 在运行 刻将 :1 掉, p_id 相当于函数里的 参。另外 程三中打 的游 标为动态 ,它也属于 动态 SQL 的范畴,其整个 编译 开发 程与 execute immediate 行的 程很 似, 里就不在 述了

3 动态SQL开发技巧

  前面分析到了,动态SQL行是以失系性能来取其灵活性的,所以行一定程度的化也是必要的,笔者根据实际开发经验给出一些开发的技巧,需要指出的是,里很多经验局限于动态SQL,有些也适用于静SQL,在描述中会注。

  技巧一:尽量使用似的SQL句,这样Oracle本身通SGA中的共享池来直接对该SQL存,那在下一次就直接存中已解析句,以此来提高行效率。

  技巧二:当及到集合元的,尽量使用批联编。比如需要id100101工的薪水加薪10%,一般情况下应该为如下形式:

  
    
declare
type num_list
is varray( 20 ) of number ;
v_id num_list :
= num_list( 100 , 101 );
begin
...
for i in v_id.first .. v_id.last loop
...
execute immediate ' update emp
set =salary*1.2
where id=:1
'
using v_id(i);
end loop;
end ;
  于上面的 理,当数据量大的 候就会 得比 慢,那 如果采用批 联编 整个集合首先一次性的 入到 SQL 引擎中 理, 这样 理效率要高的多, 行批 联编处 理的代 如下:

  
    
declare
type num_list
is varray( 20 ) of number ;
v_id num_list :
= num_list( 100 , 101 );
begin
...
forall i
in v_id.first .. v_id.last loop
...
execute immediate ' update emp
set =salary*1.2
where id=:1
'
using v_id(i);
end loop;
end ;
里是使用 forall 行批 联编 里将批 联编处 理的情形作一个小

   1) 如果一个循 行了 insert delete update 句引用了集合元素,那 可以将其移 到一个 forall 句中。

   2) 如果 select into fetch into returning into 子句引用了一个集合, 应该 使用 bulk collect 子句 行合并。

   3) 如有可能, 应该 使用主机数 实现 在程序和数据 器之 间传递 参数。

  技巧三:使用 NOCOPY 编译 器来提高 PL/SQL 性能。缺省情况下, out 型和 in out 型的参数是由 值传递 的方式 行的。但是 于大的 型或者集合 型的参数 传递 而言,其希望 耗将是很大的, 了减少 耗,可以采用引用 传递 的方式,即在 行参数声明的 候引用 NOCOPY 关键 字来 明即可到达 这样 的效果。 比如 建一个 程:

  
    
create or replace procedure test(p_object in nocopy square )
...
end ;
其中 square 一个大的 型。 这样 只是 传递 一个地址,而不是 传递 整个 象了。 这样 理也是提高了效率。

   4

  本文 对动态 SQL 编译 原理、 开发过 程以及 开发 技巧的 讨论 ,通 本文的介 后,相信 对动态 SQL 程序 开发 有了一个 体的 认识 今后深入的工作打下一个良好的基


你可能感兴趣的:(oracle)