一、静态SQL和动态SQL的概念。

  1、静态SQL

  静态SQL是我们常用的使用SQL语句的方式,就是编写PL/SQL时,SQL语句已经编写好了。因为静态SQL是在编写程序时就确定了,我们只能使用SQL中的DML和事务控制语句,但是DDL语句,以及会话控制语句却不能再PL/SQL中直接使用,如动态创建表或者某个不确定的操作时,这就需要动态SQL来实现。

  2、动态SQL

  动态SQL是指在PL/SQL编译时SQL语句是不确定的,如根据用户输入的参数的不同来执行不同的操作。编译程序对动态语句部分不进行处理,只是在程序运行时动态创建语句,对语句进行分析,病执行该语句。

  静态SQL的优势是性能较高,但不灵活。动态SQL的优势是灵活,缺点是性能稍差。

二、动态创建DML、DDL的SQL语句。

  动态创建SQL有一下几类:

  1、DDL语句、DCL语句、非查询的DML语句、单行查询的SELECT语句,这类可以使用EXECUTE IMMEDIATE语句执行。

  2、多行查询的SELECT语句可以使用游标来实现。

  3、通过DBMS_SQL程序包实现。

  下面来介绍以上3种情况:

  1、使用EXECUTE IMMEDIATE语句处理相关语句:

  语法:

  EXECUTE IMMEDIATE dynamic_sql_string

  [into define_variable_list]

  [using bind_argument_list];

  例:  

动态创建表t1
--处理DDL、DCL语句,根据用户输入的表明及字段名动态创建表t1
DECLARE
tablename VARCHAR2(20); --表名
field1 VARCHAR2(20); --字段1名称
datatype1 VARCHAR2(20); --字段1类型
field2 VARCHAR2(20); --字段2名称
datatype2 VARCHAR2(20); --字段2类型
str_sql VARCHAR2(500); --拼接SQL语句的字符串
BEGIN
tablename := 't1';
field1:='id';
datatype1:='number';
field2:='name';
datatype2:='varchar(20)';
str_sql := 'create table '||tablename||'('||field1 ||' '||datatype1||','||field2 ||' '||datatype2||')';
EXECUTE IMMEDIATE str_sql;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.put_line('操作失败!');
END;

  动态插入数据;  

--动态处理费查询的DML语句:向刚才创建的表中插入数据
DECLARE
v_id NUMBER; --输入序号;
v_name VARCHAR(20); --输入姓名;
str_sql VARCHAR2(500); --保存拼接的SQL语句
BEGIN
v_id := &vid;
v_name := '&name';
str_sql := 'insert into t1 values(:1,:2)'; --使用占位符代表变量
EXECUTE IMMEDIATE str_sql
USING v_id,v_name; --使用变量替换SQL中的占位符,v_id替换:1,v_name替换:2,依此类推。
COMMIT; --执行完毕后直接提交
END;

  查询表中的数据有多少行

--处理单行查询的SELECT举例,查询表中的数据有多少行
DECLARE
v_count NUMBER;
str_sql VARCHAR2(500);
BEGIN
str_sql := 'select count(*) from t1';
EXECUTE IMMEDIATE str_sql INTO v_count; --将查询的结果存放到变量v_count中。
DBMS_OUTPUT.put_line(v_count);
END;

  绑定变量的优缺点:

  1)可以再库缓存中共享游标,节省了CPU等资源,可以避免额外开销。

  2)SQL语句使用绑定变量可以避免被注入攻击。

  3)绑定变量是一种减少应用程序在分析查询时使用栓锁数目的可靠方法。

  

  不适合使用变量绑定的情况:

  1)对于隔相当长一段时间才执行一次的SQL语句,利用绑定变量的好处hi被不能有效利用而抵消。

  2)在数据仓库的情况下。

  3)在对建有索引的字段,且字段非常大时,利用绑定变量可能会导致查询计划错误,从而导致查询效率非常低。

  实现DDL语句中的注意事项:

  PL/SQL块使用动态SQL执行DDL语句的时候与其它不同,在DDL中不能使用绑定变量。

  实现DML语句中的注意事项:

  不能使用绑定变量替换实际的数据库对象名(表,视图,列等),只能替换字面两,如果对象名在运行时生成的,我们只能使用字符串拼接。

  2、通过游标实现多行查询的SELECT语句

  REF游标可以处理返回届国际的动态SQL。实现动态SQL的REF游标声明和普通REF游标相同,知识OPEN时绑定的是动态SQL字符串。

  例:查询emp表中所有的数据。

DECLARE
TYPE ref_cur IS REF CURSOR;
rc ref_cur;
emprow emp%ROWTYPE;
v_sql VARCHAR2(100):= 'select * from emp where deptno = :x'; --动态执行的SQL语句
BEGIN
OPEN rc FOR v_sql USING 30; --打开游标,绑定执行的SQL语句,并传递参数
LOOP
FETCH rc INTO emprow;
EXIT WHEN rc%NOTFOUND;
dbms_output.put_line('name:'||emprow.ename||' sal:'||emprow.sal);
END LOOP;
CLOSE rc;
END;

  3、DBMS_SQL程序包

  DBMS_SQL程序包是系统提供给我们的另一种使用动态SQL的方法。程序包中封装了一些列存储过程,帮助我们动态执行SQL。

  使用DBMS_SQL包实现动态SQL的步骤如下:

  1)将要执行的SQL语句或一个语句块放到一个字符串变量中。

  2)使用DBMS_SQL包的parse过程来分析该字符串。

  3)使用DBMS_SQL包的bind_variable过程来绑定变量。

  4)使用DBMS_SQL包的execute函数来执行语句。

  例:使用DBMS_SQL创建表  

DECLARE
tablename VARCHAR2(20) :='t2'; --表名
field1 VARCHAR2(20) :='id'; --字段1名称
datatype1 VARCHAR2(20) :='number'; --字段1类型
field2 VARCHAR2(20) :='name'; --字段2名称
datatype2 VARCHAR2(20) :='varchar(20)'; --字段2类型
v_sql VARCHAR2(500) := 'create table '||tablename||'('||field1 ||' '||datatype1||','||field2 ||' '||datatype2||')'; --拼接SQL语句的字符串
v_cursor NUMBER; --定义光标
v_row NUMBER; --行数
BEGIN
v_cursor:=dbms_sql.open_cursor; --为处理打开光标
dbms_sql.parse(v_cursor,v_sql,dbms_sql.native); --分析语句;
v_row:=DBMS_SQL.execute(v_cursor); --执行sql语句;
dbms_sql.close_cursor(v_cursor); --关闭光标;
DBMS_OUTPUT.put_line(v_row);
END;

  向表中插入一条数据:

DECLARE
v_id NUMBER := &vid;
v_name VARCHAR2(20) := '&vname';
v_sql VARCHAR2(100) := 'insert into t2 values(:id,:name)';
v_cursor NUMBER;
v_row NUMBER;
BEGIN
v_cursor:=dbms_sql.open_cursor;
dbms_sql.parse(v_cursor,v_sql,dbms_sql.native);
dbms_sql.bind_variable(v_cursor,':id',v_id);
dbms_sql.bind_variable(v_cursor,':name',v_name);
v_row := dbms_sql.execute(v_cursor);
dbms_sql.close_cursor(v_cursor);
COMMIT;
DBMS_OUTPUT.put_line(v_row);
END;

  查询EMP中的数据

  

DECLARE
V_DEPTNO NUMBER := &DEPTNO;
V_SQL VARCHAR2(100) := 'select empno,ename,sal from emp where deptno = :deptno';
V_CURSOR NUMBER;
V_NO NUMBER;
V_ENAME VARCHAR2(20);
V_SAL NUMBER;
v_start NUMBER;
BEGIN
V_CURSOR := DBMS_SQL.OPEN_CURSOR; --打开游标
DBMS_SQL.PARSE(V_CURSOR, V_SQL, DBMS_SQL.NATIVE); --解析动态SQL语句
DBMS_SQL.BIND_VARIABLE(V_CURSOR, ':deptno', V_DEPTNO); --传递参数 DBMS_SQL.DEFINE_COLUMN(V_CURSOR, 1, V_NO); --定义输出的列,和查询的列相匹配
DBMS_SQL.DEFINE_COLUMN(V_CURSOR, 2, V_ENAME,20);
DBMS_SQL.DEFINE_COLUMN(V_CURSOR, 3, V_SAL); v_start := DBMS_SQL.execute(V_CURSOR); --执行SQL语句,需要有接受返回值 LOOP
EXIT WHEN DBMS_SQL.FETCH_ROWS(V_CURSOR) <= 0; --解析游标,
DBMS_SQL.COLUMN_VALUE(V_CURSOR, 1, V_NO); --将当前行的数据写入上面对应的列中。
DBMS_SQL.COLUMN_VALUE(V_CURSOR, 2, V_ENAME);
DBMS_SQL.COLUMN_VALUE(V_CURSOR, 1, V_SAL); DBMS_OUTPUT.PUT_LINE('no:' || V_NO || ' enmae:' || V_ENAME ||' sal:' || V_SAL); --输出内容
END LOOP;
dbms_sql.close_cursor(v_cursor); --关闭游标
END;

Oracle基础 动态SQL语句的更多相关文章

  1. oracle 存储过程 动态sql语句

    一.在oracle项目开发中越到问题: 在利用ODP向oracle中插入数据时,如果这样写:   insert into clobTable (id, story) values(1,'....'); ...

  2. MySQL基础----动态SQL语句

    尊重原创:http://blog.csdn.net/abc19900828/article/details/39501643   动态sql语句基本语法 1 :普通SQL语句可以用Exec执行 eg: ...

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

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

  4. oracle中动态SQL使用详细介绍

    Oracle编译PL/SQL程序块分为两个种:通常静态SQL采用前一种编译方式,而动态SQL采用后一种编译方式,需要了解的朋友可以参考下     1.静态SQLSQL与动态SQL Oracle编译PL ...

  5. (转)Oracle中动态SQL详解

    本文转载自:http://www.cnblogs.com/gaolonglong/archive/2011/05/31/2064790.html 1.静态SQLSQL与动态SQL Oracle编译PL ...

  6. [转载]Oracle中动态SQL详解

    1.静态SQLSQL与动态SQL Oracle编译PL/SQL程序块分为两个种:其一为前期联编(early binding),即SQL语句在程序编译期间就已经确定,大多数的编译情况属于这种类型:另外一 ...

  7. Oracle中动态SQL详解(EXECUTE IMMEDIATE)

    Oracle中动态SQL详解(EXECUTE IMMEDIATE) 2017年05月02日 18:35:48 悠悠倾我心 阅读数:744 标签: oracle动态sqloracle 更多 个人分类:  ...

  8. MyBatis学习(三)、动态SQL语句

    三.动态SQL语句 有些时候,sql语句where条件中,需要一些安全判断,例如按某一条件查询时如果传入的参数是空,此时查询出的结果很可能是空的,也许我们需要参数为空时,是查出全部的信息.使用Orac ...

  9. 三、动态SQL语句

    //备注:该博客引自:http://limingnihao.iteye.com/blog/106076 有些时候,sql语句where条件中,需要一些安全判断,例如按某一条件查询时如果传入的参数是空, ...

随机推荐

  1. 随笔2 PAT1001.A+B Format (20)

    1001.A+B Format(20) 题目链接 1001.A+B Format (20) C++ 代码 第一次使用markdown,还不是很习惯,现在努力的在适应它 首先这道题我们很容易就可以读懂题 ...

  2. EasyUI_tree根据数据库数据生成树形结构JSON格式

    @Entitypublic class PubComp { @Id private String aguid; // 菜单ID private String pguid; // 父菜单 private ...

  3. Tomcat修改网址旁边的小图标

    用Tomcat发布时候,往往不希望用IP地址旁边的Tomcat小猫,根据需求利用自己的icon图标. 先将需要的图片转换成icon格式的. 这个网站可以进行icon格式的转换:http://www.c ...

  4. C#FTP下载文件出现远程服务器返回错误: (500) 语法错误,无法识别命令

    如果下载多个文件的时候,有时候莫名其妙的出现500服务器错误,很有可能是没有设置KeepAlive 属性导致的. 出现应用程序未处理的异常:2015/1/6 11:40:56 异常类型:WebExce ...

  5. Netty4.x分析(转)

    官网定义: netty是一个异步.事件驱动的网络应用框架,用于快速开发可维护的.高性能的服务端和客户端程序. 原理分析 Architecture Overview 网络模型:netty采用了React ...

  6. C++的优秀特性6:智能指针

    (转载请注明原创于潘多拉盒子) 智能指针(Smart Pointer)是C++非常重要的特性.考虑如下一段使用简单指针(Plain Pointer)的代码: A* a = new A(); B* b ...

  7. __declspec,__cdecl,__stdcall区别和作用

    _cdecl和__stdcall都是函数调用规范(还有一个__fastcall),规定了参数出入栈的 顺序和方法,如果只用VC编程的话可以不用关心,但是要在C++和Pascal等其他语言通信的时候就要 ...

  8. vs2010代码注释自动生成api文档

    最近做了一些接口,提供其他人调用,要写个api文档,可是我想代码注释已经写了说明,能不能直接把代码注释生成api?于是找到以下方法 环境:vs2010 先下载安装Sandcastle 和Sandcas ...

  9. MySQL中你肯定不知道的int隐情

    MySQL中定义id字段为int类型,但是你知道它内部是什么玩意吗? 1.如果定义int类型,但是不声明长度,系统默认为11个长度(这个大家都知道): 2.如果指定长度小于11,实际上系统还是默认为1 ...

  10. 自定义一个可以使用foreach语句进行迭代的类(IEnumerable)

    在c#中,凡是实现了IEnumerable接口的数据类型都可以用foreach语句进行迭代访问.所以,我们要定义一个可以使用foreach进行迭代访问的类,就必须要实现IEnumerable接口. / ...