首页 运维知识 关于Oracle基础 动态SQL语句

关于Oracle基础 动态SQL语句

一、静态SQL和动态SQL的概念。 1、静态SQL 静态SQL是我们常用的使用SQL语句的方式,就是编写PL/SQL时,SQL语句已经编写好了。因为静态SQL是在编写程序时就确定了…

一、静态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;
免责声明:文章内容不代表本站立场,本站不对其内容的真实性、完整性、准确性给予任何担保、暗示和承诺,仅供读者参考,文章版权归原作者所有。如本文内容影响到您的合法权益(内容、图片等),请及时联系本站,我们会及时删除处理。

作者: 小小编

为您推荐

dell R710 更换raid卡后,raid卡信息没有了,处理方案

dell R710 更换raid卡后,raid卡信息没有了,处理方案

1.将一台服务器(A)的硬盘依次拔出,按相同顺序插入另一台同样配置的服务器(B) 2.启动服务器(B) 3.按提示键盘按...
PL SQL Developer 13连接Oracle数据库并导出数据详细操作教程方法

PL SQL Developer 13连接Oracle数据库并导出数据详细操作教程方法

下载 并安装 PL SQL Developer 13,默认支持中文语言 ========================...
关于一条sql语句在mysql中是如何执行的

关于一条sql语句在mysql中是如何执行的

最近开始在学习mysql相关知识,自己根据学到的知识点,根据自己的理解整理分享出来,本篇文章会分析下一个sql语句在my...
关于sql注入姿势总结(mysql)

关于sql注入姿势总结(mysql)

前言 学习了sql注入很长时间,但是仍然没有系统的了解过,这次总结一波,用作学习的资料。 从注入方法分:基于报错、基于布...
关于Oracle SQL外连接

关于Oracle SQL外连接

SQL提供了多种类型的连接方式,它们之间的区别在于:从相互交叠的不同数据集合中选择用于连接的行时所采用的方法不同。 连接...

发表回复

返回顶部