ORACLE动态SQL语句
问题的提出
我们经常需要运行可变化的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语句相关推荐
- Oracle 动态SQL语句
Oracle 动态SQL语句 EXECUTE IMMEDIATE代替了以前Oracle8i中DBMS_SQLpackage包. 它解析并马上执行动态的SQL语句或非运行时创建的PL/SQL块 ...
- oracle怎么优化动态sql语句,oracle动态sql语句处理
动态SQL语句处理:根据要处理的sql语句的作用不同,可以使用三种不同类型的动态sql方法:使用execute immediate语句可以处理包括ddl(create.alter和drop).DCL( ...
- oracle 带有变量的语句_Oracle 动态SQL语句(2)之含变量的WHERE语句与日期变量
在 Oracle 动态SQL语句(1)中提到基本动态SQL语句书写,但在写动态SQL语句时特别要注意日期型变量和WHERE语句的编写. 如下代码: 1.注意在执行动态SQL语句时,execute im ...
- oracle中执行动态sql语句吗,oracle中有没有可动态执行sql语句的函数
oracle中有没有可动态执行sql语句的函数 关注:233 答案:2 手机版 解决时间 2021-03-05 15:53 提问者祗剩寂寞 2021-03-04 22:38 oracle中有没有可 ...
- 使用Oracle的DBMS_SQL包执行动态SQL语句
引用自:http://blog.csdn.net/ggjjzhzz/archive/2005/10/17/507880.aspx 在某些场合下,存储过程或触发器里的SQL语句需要动态生成.Oracle ...
- Oracle 动态游标 PL/SQL 动态SQL语句 open for [using] 语句
PL/SQL:open for [using] 语句 2017年07月19日 09:52:55 学孩儿无牙哭做粥 阅读数:681 标签: oracleSQLPLSQL 更多 个人分类: ORACLES ...
- oracle表名使用变量名,oracle 中动态sql语句,表名为变量,怎么解?
如果你用的是 Oracle 8i 及以上的版本,那简单,在过程中用 execute immediate sql_str 就行, sql_str 是一个拼凑的 SQL 语句,但这个动态语句中带参数,或 ...
- oracle 执行带参数的sql语句_Oracle动态SQL语句的简单执行
在使用ODP.NET进行Oracle编程时,有时候SQL语句非常复杂,需要采用动态构造查询语句的情况,有两种方法可以构造动态的SQL语句,并执行返回结果集. 1.在数据访问层构造SQL语句 例如下面的 ...
- Oracle中如何解决动态SQL语句过长的问题
Oracle的varchar2类型最大长度为4000,所有,如果动态sql语句过长,就没有办法在一个varchar2变量中存储整个语句,导致execute immediate本地动态sql方式无法使用 ...
- Oracle PL/SQL进阶编程(第十五弹:动态SQL语句)
理解动态SQL语句 动态SQL语句基础 动态SQL语句不仅是指SQL语句是动态拼接而成的,更主要的是SQL语句所使用的对象也是运行时期才创建的.出现这种功能跟PL/SQL本身的早起绑定特性有关,早PL ...
最新文章
- git 查看修改的代码行数,新增的文件以及删除的代码行数
- 春节假期是弯道超车的好机会!
- 提高SQL的查询效率
- Cisco开CASE方法
- python算法应用(五)——搜索与排名1(连接数据库及简单排名)
- 【JVM】 讲的比较好的JVM博客连接
- angularjsl路由_HTML5模式下的AngularJS路由404错误
- (转)质量的5大手册APQP、PPAP 、FMEA、 SPC 、MSA 是什么意思?
- 使用dea-toolbox进行数据包络分析
- sony手机刷linux,索尼Z3 Z3C 5.0系统刷recovery教程_Sony Z3第三方recovery
- Virtual Network----网卡offload特性和网络加速技术简述
- 发票核验API接口到底好用吗
- 杭州电子科技大学2020计算机研究生考研经验贴
- Python二级(04)——Python语言基本语法元素
- app注册协议做法和注意事项
- 高校教师开计算机培训中心,计算中心
- 摄影测量学和计算机视觉,科学网—摄影测量与计算机视觉——系列1 光与视觉 - 季顺平的博文...
- 植物大战僵尸 PVZ Qt版
- C语言在控制台上实现鼠标操作的方法
- pyecharts制作中国地图
热门文章
- cad导出pdf_CAD手机看图软件中导出的CAD图纸为什么没有颜色?
- 【GIS】GIS矢量空间分析(上)
- 微信小程序 - 快速搭建微信小程序demo
- UEFI引导修复教程
- 局域网 服务器禁止共享文件夹,一键设置局域网共享文件夹权限,禁止他人打印...
- android 加载ae动画,Bodymovin:Bodymovin和Lottie:把AE动画转换成HTML5/Android/iOS原生动画...
- 《算法第四版》环境搭建
- forEach(BiConsumer action)方法遍历Map集合
- JAVA JSP网上订餐系统JSP餐厅点餐系统源码JSP点餐系统JSP网上订餐系统JSP在线订餐
- 如何使用海康威视网络相机(激活+修改ip)