ORACLE之 动态 SQL 语句

动态SQL语句

静态 SQL

静态 SQL 是指直接嵌入在 PL/SQL 块中的 SQL 语句。

 

动态 SQL

动态 SQL 是指在运行 PL/SQL 块时动态输入的 SQL 语句并将 SQL 语句存放在字符串变量中,而且 SQL 居于可以包含占位符(以冒号开始)。

 

静态 SQL 和 动态 SQL 的比较


静态 SQL 是在编写 PL/SQL 块时直接嵌入的 SQL 语句;而动态 SQL 是在运行 PL/SQL 块时动态输入的 SQL 语句。
静态 SQL 性能要优于动态 SQL,因此当编写 PL/SQL 块时,如果功能完全确定,则使用静态 SQL;如果不能够确定要执行的 SQL 语句,则使用动态 SQL。

 

动态 SQL 的处理方法


1、使用 EXECUTE IMMEDIATE 语句
execute immediate 语句可以处理多数动态 SQL 操作,包括 DDL 语句(create、alter、drop)、DCL 语句(grant、revoke)、DML 语句(insert、update、delete),以及单行 select 语句。execute immediate 语句不能用于处理多行动态查询语句。
语法:
execute immediate dynamic_string
[ into { define_variable [, define_variable ]... | record } ]
[ using [ in | out | in | out ] bind_argument ], [ in | out | in | out ] bind_argument ]... ]
[ { returning | return } into bind_argument [, bind_argument ]... ];

处理无占位符和 returning 子句的 DML 语句(不需要带有 using 和 into 子句)

declare
  sql_str varchar2(100);
begin
  sql_str := 'update emp set sal=sal*1.1 where deptno=30';
  execute immediate sql_str;
end;


处理包含 returning 子句的 DML 语句

declare
  salary number(6,2);
  sql_str varchar2(100);
begin
  sql_str := 'update emp set sal=sal*(1+:percent/100)' || ' where empno=:eno returning sal into :salary';
  execute immediate sql_str using &1,&2 returning into salary;
  dbms_output.put_line('新工资:'||salary);
end;

 

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

3、使用批量动态 SQL
通过使用批量动态 SQL,可以加快 SQL 语句处理,进而提高 PL/SQL 程序的性能。

 

动态 SQL 中使用 BULK 子句


通过使用 BULK 子句,可以增加批量数据的处理速度,从而提高应用程序的性能。当使用 BULK 子句时,实际是动态 SQL 语句将变量绑定为集合元素。
当使用 BULK 子句时,集合类型必须使用 SQL 数据类型(例如: number、char 等等),而不能使用 PL/SQL 数据类型(例如:binary_integer、boolean 等)。
支持三种 BULK 子句:
1、在 EXECUTE IMMEDIATE 中使用动态 BULK 子句
语法:
execute immediate dynamic_string
[ bulk collect into define_variable [, define_variable ]...  ]
[ using bind_argument [, bind_argument... ] ]
[ { returning | return }
bulk collect into return_variable [, return_variable... ] ];

使用 BULK 子句处理多行查询

declare
  type ename_table_type is table of emp.ename%type index by binary_integer;
  ename_table ename_table_type;
  sql_str varchar2(100);
begin
  sql_str:='select ename from emp where deptno=:depno';
  execute immediate sql_str bulk collect into ename_table using &dno;
  for i in 1..ename_table.count loop
    dbms_output.put_line(ename_table(i));
  end loop;
end;

 

2、在 FETCH 中使用 BULK 子句
语法:
fetch dynamic_cursor
bulk collect into define_variable[, define_variable ... ];

示例:

declare
  type empcurtype is ref cursor;
  emp_cv empcurtype;
  type ename_table_type is table of emp.ename%type index by binary_integer;
  ename_table ename_table_type;
  sql_str varchar2(100);
begin
  sql_str := 'select ename from emp where job=:title';
  open emp_cv for sql_str using '&job';
  fetch emp_cv bulk collect into ename_table;
  for i in 1..ename_table.count loop
    dbms_output.put_line(ename_table(i));
  end loop;
  close emp_cv;
end;

 

3、在 FORALL 中使用 BUKL 子句
使用 FORALL 语句可允许在动态 SQL 语句中输入变量同时提供多个数据,但 FORALL 语句只适用于动态的 INSERT、UPDATE 和 DELETE 语句而不适用于动态的 SELECT 语句;并且 FORALL 语句和 EXECUTE IMMEDIATE 语句是结合使用的。
语法:
forall index in lower bound..upper bound
execute immediate dynamic_string
using bind_agrument | bind_agrument( index ) [, bind_agrument | bind_agrument( index ) ]...
[ { returning | return } bulk collect into bind_agrument [, bind_agrument... ] ];

修改多个雇员工资并返回新工资

declare
  type ename_table_type is table of emp.ename%type ;
  type sal_table_type is table of emp.sal%type;  
  ename_table ename_table_type;
  sal_table sal_table_type;
  sql_str varchar2(100);
begin
  ename_table := ename_table_type('SCOTT', 'SMITH', 'CLARK');
  sql_str := 'update emp set sal=sal*1.1 where ename=:1 returning sal into :2';
  forall i in 1..ename_table.count execute immediate sql_str using ename_table(i) returning bulk collect into sal_table;
  for j in 1..ename_table.count loop
    dbms_output.put_line('Empolyeer'||ename_table(j)||'''s new salary is: '||sal_table(j));
  end loop;
end;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值