您的位置:首页 > 数据库 > Oracle

Oracle系列之五——动态SQL

2014-04-08 12:48 302 查看
[b]Oracle系列之五——动态SQL [/b]

[b]一.简介[/b]

SQL语句包含静态SQL和动态SQL两种。静态SQL一般用来完成一些相对固定的任务,这种SQL在执行时已经编译完成。但是,一些PL/SQL程序要求必须在运行时建立和处理SQL语句,这种SQL语句只有在执行时才能确定,所以被称为动态SQL.

相对来说,静态SQL语句的性能要优于动态SQL语句;因而在编写PL/SQL块时,如果功能完成确定,则应该使用静态SQL;如果不能确定要执行的SQL语句,则使用动态SQL.

在PL/SQL块中编写动态SQL语句时,需要将SQL语句存放到字符串变量中,而且SQL语句可以包含占位符(以冒号开始);

[b]二.SQL的处理方法[/b]

根据动态SQL语句的不同,可以使用三种不同类型的动态SQL方法。

使用EXECUTE IMMEDIATE语句
Execute immediate语句可以处理大多数动态SQL操作,包括DDL语句(CREATE,ALTER,DROP)、DCL语句(grant,revoke)、DCL语句(INSERT,UPDATE,DELETE),以及单行SELECT语句.注意,execute immediate语句不能用于处理多行查询语句.

语法如下:

Execute immediate dynamin_string

[into {defined_variable[,define_variable]…|record}]

[using [in | out | in out] bind_argument [,in | out | in out ] bind_argument]….]

[{returning | return } into bind_argument [,bind_argument]…];

示例1,处理DDL操作:

create or replace procedure drop_table(table_name varchar2) is

sql_statement varchar2(100);

begin

sql_statement :='drop table '|| table_name;

end;

示例2,处理DCL操作

create or replace procedure grant_sys_priv(priv varchar2,

username varchar2) is

sql_state varchar2(100);

begin

sql_state :='grant '|| priv ||' to '|| username;

execute immediate sql_state;

end;

示例3,处理DML操作

在使用execute immediate语句处理DML语句时,如果DML语句即没有占位符,也没有returning语句,那么在execute immediate 语句之后不需要带有using和returing into 子句.如果DML操作包含占位符,则必须包含using 子句;如果DML语句带有returning语句,那么在EXECUTE IMMEDIATE语句之后需要带有returning into 子句.

--无占位符和returning子句

declare

sql_stat varchar2(100);

begin

sql_stat :='update emp set sal=sal*1.1';

execute immediate sql_stat;

end;

--有占位符和无returning子句

declare

sql_stat varchar2(100);

begin

sql_stat :='update emp set sal=sal*(1+:percent/100)';

execute immediate sql_stat using &1;

end;

--有占位符和returning子句

declare

sql_stat varchar2(100);

salary number(6,2);

begin

--dml语句中有returning子句

sql_stat :='update emp set sal=sal*(1+:percent/100) where empno=:no returning sal into :salary';

execute immediate sql_stat

using &1,&2

--对应的,这必须有returning into 语句

returning into salary;

dbms_output.put_line('新工资:'|| salary);

end;

--单行select语句

declare

sql_stat varchar2(100);

emp_record emp%rowtype;

begin

--占位符

sql_stat :='select * from emp where empno=:no';

execute immediate sql_stat

into emp_record

--对应的,要用using子句

using &1;

dbms_output.put_line('姓名:'|| emp_record.ename ||' 工资:'||

emp_record.sal);

end;

使用OPEN-FOR,FETCH和CLOSE语句
为了处理动态的多行查询操作,必须要使用OPEN-FOR语句打开游标,使用FETCH语句循环提取数据,最终使用CLOSE语句关闭游标.

declare

type emp_cursor_type is ref cursor;

emp_cursor emp_cursor_type;

emp_record emp%rowtype;

sql_stat varchar2(100);

begin

sql_stat :='select * from emp where deptno=:no';

open emp_cursor for sql_stat

using &no;

loop

fetch emp_cursor

into emp_record;

exit when emp_cursor%notfound;

dbms_output.put_line('name:'|| emp_record.ename ||' ,sal:'||

emp_record.sal);

end loop;

end;

使用批量动态SQL
批量动态SQL是ORACLE 9i新增加的特性.通过使用批量动态SQL,可以加快sql语句处理,进而提高PL/SQL程序的性能.

通过使用BULK子句,可以加快批量数据的处理速度,从而提高应用程序的性能.当使用Bulk子句时,实际上是动态SQL语句将变量绑定为集合元素.语法如下:

Execute immediate dynamin_string

[bulk collect into {defined_variable[,define_variable]…|record}]

[using [in | out | in out] bind_argument [,in | out | in out ] bind_argument]….]

[{returning | return } bulk collect into bind_argument [,bind_argument]…];

示例如下:

处理单行语句:

declare

type ename_table_type is table of emp.ename%type index by binary_integer;

type sal_table_type is table of emp.sal%type index by binary_integer;

ename_table ename_table_type;

sal_table sal_table_type;

sql_Stat varchar2(100);

--name emp.ename%type;

--salary emp.sal%type;

begin

sql_stat :='update emp set sal=sal*(1+:percent/100) where empno=:no returning ename,sal into :na,:sala';

execute immediate sql_Stat

using &1, &2

returning bulk collect

into ename_table, sal_table;

for i in1 .. ename_table.count loop

dbms_output.put_line('姓名:'|| ename_table(i)||' 薪水:'|| sal_table(i));

end loop;

end;

处理多行语句:

declare

type ename_table_type is table of emp.ename%type index by binary_integer;

ename_table ename_table_type;

sql_Stat varchar2(100);

begin

sql_stat :='select ename from emp';

execute immediate sql_Stat

-- using &1, &2

bulk collect

into ename_table;--, sal_table;

for i in1 .. ename_table.count loop dbms_output.put_line('姓名:'|| ename_table(i));--|| ' 薪水:' || sal_table(i)--);

end loop;

end;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: