EXECUTE IMMEDIATE and Using (incisive) -- can execute multiple sql statements

When we encounter a class of stored procedures that have similar names and process parameters, we can use executeimmediate to dynamically execute these stored procedures. In this project, I have a class of stored procedures that start with "P_InsertInto_", followed by table names such as : P_InsertInto_AC01, P_InsertInto_AC02, etc., are used to insert data into AC01, AC02........ these tables, we can only use executeimmediate to dynamically execute these processes, which will be much more convenient in terms of speed and code writing .
This method has been studied for a long time, and it is not easy, huh, huh. . . . , and finally succeeded!
My understanding of the usage of executeimmediate is illustrated with an example. There is a stored procedure named: p_test, which has three parameters: two input parameters and one output parameter. The implementation process is as follows:
declare
v_sql varchar2(1000);
c varchar2(1000);
a varchar2(1) :='1';
b number :=1;
begin
-- of course, dynamic stored procedures can be implemented here, just put them directly into the variable v_sql (here is A specified procedure p_test)
v_sql:='begin p_test(:v1,:v2,:v3); end;';
executeimmediate v_sql using in '1',in '2',out c;
--or executeimmediate v_sql using ' 1', '2',out c;
dbms_output.put_line(c);
end;
Above we have implemented the calling method of dynamically passing parameters and dynamic stored procedures. It is worth noting that: the default is in, in can be saved, out cannot be saved!
Another point worth noting is that each dynamic (executeimmediate) method has its own begin.........end; just wrap it, if there are more than one, write it like this:
-- The first
begin
v_sql:='begin p_test1(:v1,:v2,:v3); end;';
executeimmediate v_sql using in '1',in '2',out c;
--or executeimmediate v_sql using '1' , '2',out c;
dbms_output.put_line(c);
end; --the
second
begin
v_sql:='begin p_test2(:v1,:v2,:v3); end;';
executeimmediate v_sql using in '1 ',in '2',out c;
--or executeimmediate v_sql using '1', '2',out c;
dbms_output.put_line(c);
end;
. . . . . . .
--Nth
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比以前可能用到的更容易并且更高效.当意图执行动态语句时,适当地处理异常更加重要.应该关注于捕获所有可能的异常.

 

====================================================

 

来自:http://blog.sina.com.cn/s/blog_6f07b6eb0100oi45.html

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326181808&siteId=291194637