EXECUTE IMMEDIATE和Using的用法

一、 EXECUTE IMMEDIATE的作用:

        简单来说 就是你一个存储过程当中 创建了一个表 table_a 然后要用insert into将其他的数据插入到这个table_a当中,但是因为你在创建过程的时候 table_a还不存在,过程就会显示有编译错误,因为table_a不存在必然导致过程无法执行,所以无法编译成功,而把insert into语句加如到 execute immediate之后 则oracle不会再去理会这个对象是否存在,因此可以成功编译和执行。
       执行动态SQL语句,举例str := ‘select *  from test’;execute immediate str;多用于拼接的SQL


二、实例

    有一个存储过程名为:p_test,它有三个参数,分别为:两个输入参数和一个输出参数,实现过程如:
declare
v_sql varchar2(1000);
c varchar2(1000);
a varchar2(1) :='1';
b number :=1;
begin
--当然动态存储过程可以在这实现了,直接放到v_sql这个变量中就可以了(在这里是一个指定的过程p_test)
v_sql:='begin p_test(:v1,:v2,:v3); end;';
executeimmediate v_sql using in '1',in '2',out c;
--或executeimmediate v_sql using '1', '2',out c;
dbms_output.put_line(c);
end;
上面我们就实现了动态传递参数和动态存储过程的调用方法。值得注意的是:默认为in,in可省,out不可省!
还有一个值得注意的地方就是:每一个动态(executeimmediate)执行的方法都有自己的begin.........end;包住才行呀,如果有多个就这样写:
--第一个
begin
v_sql:='begin p_test1(:v1,:v2,:v3); end;';
executeimmediate v_sql using in '1',in '2',out c;
--或executeimmediate v_sql using '1', '2',out c;
dbms_output.put_line(c);
end;
--第二个
begin
v_sql:='begin p_test2(:v1,:v2,:v3); end;';
executeimmediate v_sql using in '1',in '2',out c;
--或executeimmediate v_sql using '1', '2',out c;
dbms_output.put_line(c);
end;
。。。。。。。
--第N个
begin
--
end;

 

 

EXECUTEIMMEDIATE代替了以前Oracle8i中DBMS_SQL package包.它解析并马上执行动态的SQL语句或非运行时创建的PL/SQL块.动态创建和执行SQL语句性能超前,EXECUTEIMMEDIATE的目标在于减小企业费用并获得较高的性能,较之以前它相当容易编码.尽管DBMS_SQL仍然可用,但是推荐使用EXECUTEIMMEDIATE,因为它获的收益在包之上。

使用技巧

 

1. EXECUTEIMMEDIATE将不会提交一个DML事务执行,应该显式提交
如果通过EXECUTEIMMEDIATE处理DML命令,那么在完成以前需要显式提交或者作为EXECUTEIMMEDIATE自己的一部分. 如果通过EXECUTEIMMEDIATE处理DDL命令,它提交所有以前改变的数据

 

2. 不支持返回多行的查询,这种交互将用临时表来存储记录(参照例子如下)或者用REF cursors.

 

3. 当执行SQL语句时,不要用分号,当执行PL/SQL块时,在其尾部用分号.

 

4. 在Oracle手册中,未详细覆盖这些功能。下面的例子展示了所有用到Executeimmediate的可能方面.希望能给你带来方便.

 

5. 对于Forms开发者,当在PL/SQL 8.0.6.3.版本中,Forms 6i不能使用此功能.

 

EXECUTEIMMEDIATE用法例子

 

1. 在PL/SQL运行DDL语句


begin
executeimmediate 'set role all';
end;

 

2. 给动态语句传值(USING 子句)


declare
l_depnam varchar2(20) := 'testing';
l_loc    varchar2(10) := 'Dubai';
begin
executeimmediate 'insert into dept values (:1, :2, :3)'
    using 50, l_depnam, l_loc;
commit;
end;

 

3. 从动态语句检索值(INTO子句)


declare
l_cnt    varchar2(20);
begin
executeimmediate 'select count(1) from emp'
    into l_cnt;
dbms_output.put_line(l_cnt);
end;

 

4. 动态调用例程.例程中用到的绑定变量参数必须指定参数类型.黓认为IN类型,其它类型必须显式指定

 

declare
l_routin   varchar2(100) := 'gen2161.get_rowcnt';
l_tblnam   varchar2(20) := 'emp';
l_cnt      number;
l_status   varchar2(200);
begin
executeimmediate 'begin ' || l_routin || '(:2, :3, :4); end;'
    using in l_tblnam, out l_cnt, in out l_status;

if l_status != 'OK' then
     dbms_output.put_line('error');
end if;
end;

 

5. 将返回值传递到PL/SQL记录类型;同样也可用%rowtype变量


declare
type empdtlrec is record (empno number(4),
                           ename varchar2(20),
                           deptno number(2));
empdtl empdtlrec;
begin
executeimmediate 'select empno, ename, deptno ' ||
                   'from emp where empno = 7934'
    into empdtl;
end;

 

6. 传递并检索值.INTO子句用在USING子句前

 

declare
l_dept    pls_integer := 20;
l_nam     varchar2(20);
l_loc     varchar2(20);
begin
executeimmediate 'select dname, loc from dept where deptno = :1'
    into l_nam, l_loc
    using l_dept ;
end;

 

7. 多行查询选项.对此选项用insert语句填充临时表,用临时表进行进一步的处理,也可以用REF cursors纠正此缺憾.

declare
l_sal   pls_integer := 2000;
begin
executeimmediate 'insert into temp(empno, ename) ' ||
                   '          select empno, ename from emp ' ||
                   '          where sal > :1'
    using l_sal;
commit;
end;

 

       对于处理动态语句,EXECUTEIMMEDIATE比以前可能用到的更容易并且更高效.当意图执行动态语句时,适当地处理异常更加重要.应该关注于捕获所有可能的异常.


三、Using用法简介

1.静态SQLSQL与动态SQL

Oracle编译PL/SQL程序块分为两个种:
其一为前期联编(early binding),即SQL语句在程序
编译期间就已经确定,大多数的编译情况属于这种类型;
另外一种是后期联编(late binding),即SQL语句只有在
运行阶段才能建立,例如当查询条件为用户输入时,
那么Oracle的SQL引擎就无法在编译期对该程序语句进行确定,只能在用户输入一定的查询条件后才能提交给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;

你可能感兴趣的:(EXECUTE IMMEDIATE和Using的用法)