问题的提出

我们经常需要运行可变化的SQL语句,这种通常称为动态SQL,在ORACLE中执行动态的SQL语句,需要了解ORACLE的动态SQL语句的相关规定。
SQL动态语句是由程序或者存储过程生成的SQL语句,这种语句的特点是,不能简单的去运行。因为它不是标准的,其中含有变化的成分,因此ORACLE提供了一个执行动态SQL语句的模式:
EXECUTE IMMEDIATE
这句话的含义是立即执行,而不先去进行语法检查,在执行过程中可能会发生逻辑错误,则通过错误中断进行处理。

一种动态SQL的方法

/***DBMS_OUTPUT.PUT_LINE(uSQL);p_Money_TJCALL p_Money_TJ();测试在SQL*PLUS下进行VAR r refcursor;Exec p_Money_TJ(:r);print r;
***/
CREATE OR REPLACE PROCEDURE p_Money_TJ(p_cur out sys_refcursor)
AS-- 变量定义Cursor CC IS
SELECT FTYPE FROM APP_MONEY GROUP BY FTYPE;
uSQL VARCHAR2(32600);
BEGINuSQL :=         'BEGIN OPEN :p_cur for ';uSQL := uSQL || 'SELECT FMID 会员账号,F_GETXM(FMID) 会员姓名';FOR C IN CC LOOPuSQL := uSQL || ',SUM(CASE WHEN FTYPE = '''||C.FTYPE||''' THEN FMONEY END) '||C.FTYPE;END LOOP;uSQL := uSQL || ' FROM APP_MONEY GROUP BY FMID';uSQL := uSQL || '; END;';EXECUTE IMMEDIATE uSQL USING p_cur;
END;

使用动态游标

1、声明动态游标

TYPE cc_type IS REF CURSOR;

2、声明游标变量

my_cursor cc_type;

3、使用游标

n_deptno:=20;
uSQL := 'SELECT empno,ename FROM emp WHERE deptno = '||n_deptno;
OPEN my_cursor FOR uSQL;
LOOP FETCH my_cursor INTO n_empno,v_ename;EXIT WHEN my_cursor%NOTFOUND;--用n_empno,v_ename做其它处理--....
END LOOP;
CLOSE my_cursor;

4、小结
动态游标可以胜任大多数动态SQL的需求了,使用简洁方便。

使用 EXECUTE IMMEDIATE

最早大家都使用DBMS_SQL包,但是太太麻烦了,最终都放弃了。但是自从有了EXECUTE IMMEDIATE之后,但要注意以下几点:
EXECUTE IMMEDIATE代替了以前 Oracle8i 中 DBMS SQL package包, 它解析并马上执行动态的SQL语句或非运行时创建的PL/SQL块。动态创建和执行SQL语句性能超前,EXECUTE IMMEDIATE的目标在于减小企业费用并获得较高的性能,较之以前它相当容易编码。尽管DBMS_SQL仍然可用,但是推荐使用EXECUTE IMMEDIATE,因为它获的收益在包之上。
使用技巧
1. EXECUTE IMMEDIATE将不会提交一个DML事务执行,应该显式提交如果通过EXECUTE IMMEDIATE处理DML命令,那么在完成以前需要显式提交或者作为EXECUTE IMMEDIATE自己的一部分. 如果通过EXECUTE IMMEDIATE处理DDL命令,它提交所有以前改变的数据
2. 不支持返回多行的查询,这种交互将用临时表来存储记录(参照例子如下)或者用REF cursors.
3. 当执行SQL语句时,不要用分号,当执行PL/SQL块时,在其尾部用分号.
4. 在Oracle手册中,未详细覆盖这些功能。下面的例子展示了所有用到Execute immediate的可能方面.希望能给你带来方便.
5. 对于Forms开发者,当在PL/SQL 8.0.6.3.版本中,Forms 6i不能使用此功能.

EXECUTE IMMEDIATE用法例子

1. 在PL/SQL运行DDL语句

beginexecute immediate 'set role all';
end;

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

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

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

declarel_cnt    varchar2(20);
beginexecute immediate 'select count(1) from emp'into l_cnt;dbms_output.put_line(l_cnt);
end;

4. 动态调用例程

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

declarel_routin   varchar2(100) := 'gen2161.get_rowcnt';l_tblnam   varchar2(20) := 'emp';l_cnt      number;l_status   varchar2(200);
beginexecute immediate 'begin ' || l_routin || '(:2, :3, :4); end;'using in l_tblnam, out l_cnt, in out l_status;if l_status != 'OK' thendbms_output.put_line('error');end if;
end;

5. 将返回值传递到PL/SQL记录类型

同样也可用%rowtype变量

declaretype empdtlrec is record (empno  number(4),ename  varchar2(20),deptno  number(2));empdtl empdtlrec;
beginexecute immediate 'select empno, ename, deptno '||'from emp where empno = 7934'into empdtl;
end;

6. 传递并检索值

INTO子句用在USING子句前

declarel_dept    pls_integer := 20;l_nam     varchar2(20);l_loc     varchar2(20);
beginexecute immediate 'select dname, loc from dept where deptno = :1'into l_nam, l_locusing l_dept ;
end;

7. 多行查询选项

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

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

对于处理动态语句,EXECUTE IMMEDIATE比以前可能用到的更容易并且更高效.当意图执行动态语句时,适当地处理异常更加重要.应该关注于捕获所有可能的异常.
Oracle 动态SQL
Oracle 动态SQL有两种写法:用 DBMS_SQL 或 execute immediate,建议使用后者。试验步骤如下:

1. DDL 和 DML

/*** DDL ***/
begin  EXECUTE IMMEDIATE 'drop table temp_1';  EXECUTE IMMEDIATE 'create table temp_1(name varchar2(8))';
end;  /*** DML ***/
declare  v_1 varchar2(8);  v_2 varchar2(10);  str varchar2(50);
begin  v_1:='测试人员';  v_2:='北京';  str := 'INSERT INTO test (name ,address) VALUES (:1, :2)';  EXECUTE IMMEDIATE str USING v_1, v_2;  commit;
end;  

2. 返回单条结果

declare  str varchar2(500);  c_1 varchar2(10);  r_1 test%rowtype;
begin  c_1:='测试人员';  str:='select * from test where name=:c WHERE ROWNUM=1';  execute immediate str into r_1 using c_1;  DBMS_OUTPUT.PUT_LINE(R_1.NAME||R_1.ADDRESS);
end ;  

3. 返回结果集

CREATE OR REPLACE package pkg_test as  /* 定义ref cursor类型  不加return类型,为弱类型,允许动态sql查询,  否则为强类型,无法使用动态sql查询;  */  type myrctype is ref cursor;  --函数申明  function get(intID number) return myrctype;
end pkg_test;
/  CREATE OR REPLACE package body pkg_test as
--函数体  function get(intID number) return myrctype is  rc myrctype; --定义ref cursor变量  sqlstr varchar2(500);  begin  if intID=0 then  --静态测试,直接用select语句直接返回结果  open rc for select id,name,sex,address,postcode,birthday from
student;  else  --动态sql赋值,用:w_id来申明该变量从外部获得  sqlstr := 'select id,name,sex,address,postcode,birthday from student
where id=:w_id';  --动态测试,用sqlstr字符串返回结果,用using关键词传递参数  open rc for sqlstr using intid;  end if;
return rc;  end get;  end pkg_test;  

ORACLE动态SQL语句相关推荐

  1. Oracle 动态SQL语句

    Oracle 动态SQL语句     EXECUTE IMMEDIATE代替了以前Oracle8i中DBMS_SQLpackage包.  它解析并马上执行动态的SQL语句或非运行时创建的PL/SQL块 ...

  2. oracle怎么优化动态sql语句,oracle动态sql语句处理

    动态SQL语句处理:根据要处理的sql语句的作用不同,可以使用三种不同类型的动态sql方法:使用execute immediate语句可以处理包括ddl(create.alter和drop).DCL( ...

  3. oracle 带有变量的语句_Oracle 动态SQL语句(2)之含变量的WHERE语句与日期变量

    在 Oracle 动态SQL语句(1)中提到基本动态SQL语句书写,但在写动态SQL语句时特别要注意日期型变量和WHERE语句的编写. 如下代码: 1.注意在执行动态SQL语句时,execute im ...

  4. oracle中执行动态sql语句吗,oracle中有没有可动态执行sql语句的函数

    oracle中有没有可动态执行sql语句的函数 关注:233  答案:2  手机版 解决时间 2021-03-05 15:53 提问者祗剩寂寞 2021-03-04 22:38 oracle中有没有可 ...

  5. 使用Oracle的DBMS_SQL包执行动态SQL语句

    引用自:http://blog.csdn.net/ggjjzhzz/archive/2005/10/17/507880.aspx 在某些场合下,存储过程或触发器里的SQL语句需要动态生成.Oracle ...

  6. Oracle 动态游标 PL/SQL 动态SQL语句 open for [using] 语句

    PL/SQL:open for [using] 语句 2017年07月19日 09:52:55 学孩儿无牙哭做粥 阅读数:681 标签: oracleSQLPLSQL 更多 个人分类: ORACLES ...

  7. oracle表名使用变量名,oracle 中动态sql语句,表名为变量,怎么解?

    如果你用的是 Oracle 8i 及以上的版本,那简单,在过程中用 execute immediate sql_str 就行, sql_str 是一个拼凑的 SQL 语句,但这个动态语句中带参数,或 ...

  8. oracle 执行带参数的sql语句_Oracle动态SQL语句的简单执行

    在使用ODP.NET进行Oracle编程时,有时候SQL语句非常复杂,需要采用动态构造查询语句的情况,有两种方法可以构造动态的SQL语句,并执行返回结果集. 1.在数据访问层构造SQL语句 例如下面的 ...

  9. Oracle中如何解决动态SQL语句过长的问题

    Oracle的varchar2类型最大长度为4000,所有,如果动态sql语句过长,就没有办法在一个varchar2变量中存储整个语句,导致execute immediate本地动态sql方式无法使用 ...

  10. Oracle PL/SQL进阶编程(第十五弹:动态SQL语句)

    理解动态SQL语句 动态SQL语句基础 动态SQL语句不仅是指SQL语句是动态拼接而成的,更主要的是SQL语句所使用的对象也是运行时期才创建的.出现这种功能跟PL/SQL本身的早起绑定特性有关,早PL ...

最新文章

  1. git 查看修改的代码行数,新增的文件以及删除的代码行数
  2. 春节假期是弯道超车的好机会!
  3. 提高SQL的查询效率
  4. Cisco开CASE方法
  5. python算法应用(五)——搜索与排名1(连接数据库及简单排名)
  6. 【JVM】 讲的比较好的JVM博客连接
  7. angularjsl路由_HTML5模式下的AngularJS路由404错误
  8. (转)质量的5大手册APQP、PPAP 、FMEA、 SPC 、MSA 是什么意思?
  9. 使用dea-toolbox进行数据包络分析
  10. sony手机刷linux,索尼Z3 Z3C 5.0系统刷recovery教程_Sony Z3第三方recovery
  11. Virtual Network----网卡offload特性和网络加速技术简述
  12. 发票核验API接口到底好用吗
  13. 杭州电子科技大学2020计算机研究生考研经验贴
  14. Python二级(04)——Python语言基本语法元素
  15. app注册协议做法和注意事项
  16. 高校教师开计算机培训中心,计算中心
  17. 摄影测量学和计算机视觉,科学网—摄影测量与计算机视觉——系列1 光与视觉 - 季顺平的博文...
  18. 植物大战僵尸 PVZ Qt版
  19. C语言在控制台上实现鼠标操作的方法
  20. pyecharts制作中国地图

热门文章

  1. cad导出pdf_CAD手机看图软件中导出的CAD图纸为什么没有颜色?
  2. 【GIS】GIS矢量空间分析(上)
  3. 微信小程序 - 快速搭建微信小程序demo
  4. UEFI引导修复教程
  5. 局域网 服务器禁止共享文件夹,一键设置局域网共享文件夹权限,禁止他人打印...
  6. android 加载ae动画,Bodymovin:Bodymovin和Lottie:把AE动画转换成HTML5/Android/iOS原生动画...
  7. 《算法第四版》环境搭建
  8. forEach(BiConsumer action)方法遍历Map集合
  9. JAVA JSP网上订餐系统JSP餐厅点餐系统源码JSP点餐系统JSP网上订餐系统JSP在线订餐
  10. 如何使用海康威视网络相机(激活+修改ip)