ORACLE中DBMS_SQL的用法
 
对于一般的select操作,如果使用动态的sql语句则需要进行以下几个步骤:
open   cursor---> parse---> define   column---> excute---> fetch   rows---> close   cursor;
而对于dml操作(insert,update)则需要进行以下几个步骤:
open   cursor---> parse---> bind   variable---> execute---> close   cursor;
对于delete操作只需要进行以下几个步骤:
open   cursor---> parse---> execute---> close   cursor;
  www.2cto.com  
例一:
create table test(n_id   number,  v_name  varchar2(50), d_insert_date date);
alter table test add constraint pk_id  primary key(n_id);
 
declare
   v_cursor   number;
   v_sql      varchar2(200);
   v_id       number;
   v_name     varchar2(50);
   v_date     date;
   v_stat     number;
begin
  
   v_id := 1;
   v_name := '测试 insert';
   v_date := sysdate;
   v_cursor := dbms_sql.open_cursor;  --打开游标
   v_sql := 'insert into test(n_id, v_name, d_insert_date) values(:v_id,:v_name,:v_date)';
   dbms_sql.parse(v_cursor, v_sql, dbms_sql.native);  --解析SQL
   dbms_sql.bind_variable(v_cursor, ':v_id', v_id);   --绑定变量
   dbms_sql.bind_variable(v_cursor, ':v_name', v_name);
   dbms_sql.bind_variable(v_cursor, ':v_date', v_date);
  
   v_stat := dbms_sql.execute(v_cursor);  --执行
   dbms_sql.close_cursor(v_cursor);   --关闭游标
   commit;
end;
  www.2cto.com  
例二:
 
declare
   v_cursor   number;
   v_sql      varchar2(200);
   v_id       number;
   v_name     varchar2(50);
   v_stat     number;
begin
    v_name := '测试 update';
    v_id := 1;
    v_cursor := dbms_sql.open_cursor;
    v_sql := 'update test set v_name = :v_name, d_insert_date = :v_date where n_id = :v_id';
    dbms_sql.parse(v_cursor, v_sql, dbms_sql.native);
    dbms_sql.bind_variable(v_cursor, ':v_name', v_name);
    dbms_sql.bind_variable(v_cursor, ':v_date', sysdate);
    dbms_sql.bind_variable(v_cursor, ':v_id', v_id);
    v_stat := dbms_sql.execute(v_cursor);
    dbms_sql.close_cursor(v_cursor);
    commit;
end;
  www.2cto.com  
例三:
 
declare
    v_cursor   number;
    v_sql      varchar2(200);
    v_id       number;
    v_stat     number;
begin
 
   v_id := 1;
   v_sql := 'delete from test where n_id = :v_id';
   v_cursor := dbms_sql.open_cursor;
   dbms_sql.parse(v_cursor, v_sql, dbms_sql.native);
   dbms_sql.bind_variable(v_cursor, ':v_id', v_id);
   v_stat := dbms_sql.execute(v_cursor);
   dbms_sql.close_cursor(v_cursor);
   commit;
end;
 
例四:
 
declare
   v_cursor    number;
   v_sql       varchar2(200);
   v_id        number;
   v_name      varchar2(50);
   v_date      varchar2(10);
   v_stat      number;
begin
 
    v_sql := 'select n_id, v_name, to_char(d_insert_date, ''yyyy-mm-dd'') from test';
    v_cursor := dbms_sql.open_cursor;              --打开游标
    dbms_sql.parse(v_cursor, v_sql, dbms_sql.native);  --解析游标
    dbms_sql.define_column(v_cursor, 1, v_id);         --定义列
    dbms_sql.define_column(v_cursor, 2, v_name, 50);   --注意:当变量为varchar2类型时,要加长度  www.2cto.com  
    dbms_sql.define_column(v_cursor, 3, v_date, 10);
    v_stat := dbms_sql.execute(v_cursor);        --执行SQL
    loop
        exit when dbms_sql.fetch_rows(v_cursor) <= 0;  --fetch_rows在结果集中移动游标,如果未抵达末尾,返回1。
        dbms_sql.column_value(v_cursor, 1, v_id);   --将当前行的查询结果写入上面定义的列中。
        dbms_sql.column_value(v_cursor, 2, v_name);
        dbms_sql.column_value(v_cursor, 3, v_date);
        dbms_output.put_line(v_id || ':' || v_name || ':' || v_date);
    end loop;
end;
 
--------------------------------------------------------------------------------------------------
PL/SQL中使用动态SQL编程
 
    在PL/SQL程序设计过程中,会遇到很多必须使用动态sql的地方,oracle系统所tb提供的DMBS_SQL包可以帮助你解决问题。
(一)介绍
 
    DBMS_SQL系统包提供了很多函数及过程,现在简要阐述其中使用频率较高的几种:
 
    function open_cursor:打开一个动态游标,并返回一个整型;
 
    procedure close_cursor(c in out integer) :关闭一个动态游标,参数为open_cursor所打开的游标;
  www.2cto.com  
    procedure parse(c in integer, statement in varchar2, language_flag in integer):对动态游标所提供的sql语句进行解析,参数C表示游标,statement为sql语句,language-flag为解析sql语句所用oracle版本,一般有V6,V7跟native(在不明白所连database版本时,使用native);
 
    procedure define_column(c in integer, position in integer, column any datatype, [column_size in integer]):定义动态游标所能得到的对应值,其中c为动态游标,positon为对应动态sql中的位置(从1开始),column为该值所对应的变量,可以为任何类型,column_size只有在column为定义长度的类型中使用如VARCHAR2,CHAR等(该过程有很多种情况,此处只对一般使用到的类型进行表述);
 
    function execute(c in integer):执行游标,并返回处理一个整型,代表处理结果(对insert,delete,update才有意义,而对select语句而言可以忽略);
 
    function fetch_rows(c in integer):对游标进行循环取数据,并返回一个整数,为0时表示已经取到游标末端;
 
    procedure column_value(c in integer, position in integer, value):将所取得的游标数据赋值到相应的变量,c为游标,position为位置,value则为对应的变量;
 
    procedure bind_variable(c in integer, name in varchar2, value):定义动态sql语句(DML)中所对应字段的值,c为游标,name为字段名称,value为字段的值;
 
    以上是在程序中经常使用到的几个函数及过程,其他函数及过程请参照oracle所提供定义语句dbmssql.sql
 
(二)一般过程
  www.2cto.com  
    对于一般的select操作,如果使用动态的sql语句则需要进行以下几个步骤:
    open cursor--->parse--->define column--->excute--->fetch rows--->close cursor;
    而对于dml操作(insert,update)则需要进行以下几个步骤:
    open cursor--->parse--->bind variable--->execute--->close cursor;
    对于delete操作只需要进行以下几个步骤:
    open cursor--->parse--->execute--->close cursor;
 
(三)具体案例
 
    下面就本人所开发系统中某一程序做分析
    该过程为一股票技术曲线计算程序,将数据从即时数据表中取出,并按照计算曲线的公式,tb对这些数据进行计算,并将结果保存到技术曲线表中.
 
create or replace procedure R_Ma_Main
  (  www.2cto.com  
   pid varchar2,
   pend varchar2,
   pinterval varchar2,
   totab varchar2
  ) is                      
  
--定义数组
type Date_type is table of varchar2(12) index by binary_integer;
type Index_type is table of number index by binary_integer;
 
TempDate Date_Type;--时间数组
TempIndex Index_Type;--股票收盘价数组
TempMa Index_Type;--ma技术曲线数据
 
cursor1 integer;--游标
cursor2 integer;--游标
rows_processed integer;--执行游标返回
 
TempInter integer;--参与计算数值个数
TempVal integer;--计算时间类型
TempSql varchar2(500);--动态sql语句
MyTime varchar2(12);--时间
MyIndex number;--数值
MidIndex number;--中间变量
i integer := 999;
j integer;
begin  www.2cto.com  
  TempInter := to_number(substr(pinterval,1,4));
  TempVal := to_number(substr(pinterval,5,2));
  TempSql := R_GetSql1(pid, pend, TempVal);--得到选择数据的sql语句
 
  --得到当天的即时数据,并依次保存到数组中
  cursor1 := dbms_sql.open_cursor;  --创建游标
  dbms_sql.parse(cursor1, TempSql, dbms_sql.native);  --解析动态sql语句,取两个字段,时间及价格,其中时间以14位的varchar2表示
  dbms_sql.define_column(cursor1, 1, MyTime, 12);  --分别定义sql语句中各字段所对应变量
  dbms_sql.define_column(cursor1, 2, MyIndex);
  rows_processed := dbms_sql.execute(cursor1);
  loop
 
    if dbms_sql.fetch_rows(cursor1) > 0 then
      begin
        dbms_sql.column_value(cursor1, 1, MyTime);
        dbms_sql.column_value(cursor1, 2, MyIndex);
        TempDate(i) := MyTime;
        TempIndex(i) := MyIndex;
        i := i - 1;--按倒序的方法填入数组
      end;
    else
      exit;
    end if;
  end loop;
  dbms_sql.close_cursor(cursor1);
  
  --如果取得的数据量不够计算个数,则跳出程序
  if i > 999-TempInter then
    goto JumpLess;
  end if;
  
  --初始化中间变量
  MidIndex := 0;
  TempIndex(i) := 0;
  for j in i..i+TempInter-1 loop
    MidIndex := MidIndex + TempIndex(j);
  end loop; 
  www.2cto.com  
  --依次对当天数据计算ma值,并保存到ma数组中
  for j in i+TempInter..999 loop
    MidIndex := MidIndex - TempIndex(j-TempInter) + TempIndex(j);
    TempMa(j) := MidIndex/TempInter;
  end loop;   
 
  if TempVal < 6 then--如果计算的是分钟跟天的ma技术曲线
    begin
    cursor2 := dbms_sql.open_cursor;
    TempSql := 'insert into ' || totab || ' values(:r_no, :i_interval, :i_time, :i_index)';
    dbms_sql.parse(cursor2, TempSql, dbms_sql.native); 
    for j in i+TempInter..999 loop
      dbms_sql.bind_variable(cursor2, 'r_no', pid);
      dbms_sql.bind_variable(cursor2, 'i_interval', pinterval);
      dbms_sql.bind_variable(cursor2, 'i_time', TempDate(j));
      dbms_sql.bind_variable(cursor2, 'i_index', TempMa(j));
      rows_processed := dbms_sql.execute(cursor2);--插入数据
    end loop;
    end;
  end if; 
  commit;
  dbms_sql.close_cursor(cursor2);
  --数据量不足跳出
  <<JumpLess>>
  null;
  
  --exception处理,无关本话题
end;
/
  www.2cto.com  
(四)个人观点
 
    在使用dbms_sql系统包的过程中,其方法简单而又不失灵活,但还是需要注意一些问题:
    1、在整个程序的设计过程中,对游标的操作切不可有省略的部分,一旦省略其中某一步骤,则会程序编译过程既告失败,如在程序结尾处未对改游标进行关闭操作,则在再次调用过程时会出现错误.
    2、dbms_sql除了可以做一般的select,insert,update,delete等静态的sql做能在过程中所做工作外,还能执行create等DDL操作,不过在执行该类操作时应首先显式赋予执行用户相应的系统权限,比如create table等.该类操作只需open cursor--->prase--->close cursor即能完成.
 
    以上为本人在工作中对dbms_sql的一点点看法,不到之处,请予指正.
    对于想更深了解dbms_sql的朋友,请阅读dbmssql.sql文件.
   www.2cto.com  
附个Oracle自带的流程说明(强大啊):
 
  --  The flow of procedure calls will typically look like this:
  --
  --                      -----------
  --                    | open_cursor |
  --                      -----------
  --                           |
  --                           |
  --                           v
  --                         -----
  --          ------------>| parse |
  --         |               -----
  --         |                 |
  --         |                 |---------
  --         |                 v         |
  --         |           --------------  |
  --         |-------->| bind_variable | |
  --         |     ^     -------------   |
  --         |     |           |         |
  --         |      -----------|         |
  --         |                 |<--------
  --         |                 v  www.2cto.com  
  --         |               query?---------- yes ---------
  --         |                 |                           |
  --         |                no                           |
  --         |                 |                           |
  --         |                 v                           v
  --         |              -------                  -------------
  --         |----------->| execute |            ->| define_column |
  --         |              -------             |    -------------
  --         |                 |------------    |          |
  --         |                 |            |    ----------|
  --         |                 v            |              v
  --         |           --------------     |           -------
  --         |       ->| variable_value |   |  ------>| execute |
  --         |      |    --------------     | |         -------
  --         |      |          |            | |            |
  --         |       ----------|            | |            |
  --         |                 |            | |            v
  --         |                 |            | |        ----------
  --         |                 |<-----------  |----->| fetch_rows |
  --         |                 |              |        ----------
  --         |                 |              |            |
  --         |                 |              |            v
  --         |                 |              |    --------------------
  --         |                 |              |  | column_value         |
  --         |                 |              |  | variable_value       |
  --         |                 |              |    ---------------------
  --         |                 |              |            |
  --         |                 |<--------------------------
  --         |                 |
  --          -----------------|  www.2cto.com  
  --                           |
  --                           v
  --                      ------------
  --                    | close_cursor |
  --                      ------------ 
  --
  ---------------

ORACLE中DBMS_SQL的用法的更多相关文章

  1. Oracle 中 decode 函数用法

    Oracle 中 decode 函数用法 含义解释:decode(条件,值1,返回值1,值2,返回值2,...值n,返回值n,缺省值) 该函数的含义如下:IF 条件=值1 THEN RETURN(翻译 ...

  2. Oracle中group by用法

    Oracle中group by用法 在select 语句中可以使用group by 子句将行划分成较小的组,一旦使用分组后select操作的对象变为各个分组后的数据,使用聚组函数返回的是每一个组的汇总 ...

  3. oracle中to_date详细用法示例(oracle日期格式转换)

    这篇文章主要介绍了oracle中to_date详细用法示例,包括期和字符转换函数用法.字符串和时间互转.求某天是星期几.两个日期间的天数.月份差等用法 TO_DATE格式(以时间:2007-11-02 ...

  4. oracle中类似indexof用法_instr函数

    oracle中类似indexof用法_instr函数 [sql] 在oracle中没有indexof()函数 但是提供了一个 instr() 方法 具体用法: select instr('保定市南市区 ...

  5. Oracle中的rownum用法解析

    注意:rownum从1开始:  1.rownum按照记录插入时的顺序给记录排序,所以有order by的子句时一定要注意啊!  2.使用时rownum,order by字段是否为主键有什么影响?  3 ...

  6. Oracle中rownum的用法

    rownum是Oracle对查询结果进行顺序编号,第一行分配1,第二行2,以此类推.rownum不能以任何表的名称作为前缀. rownum这个伪字段可以用于控制返回的记录行数. 例如表:student ...

  7. oracle中临时表的用法详解

    转至:https://blog.csdn.net/mystonelxj/article/details/85010856?utm_medium=distribute.pc_relevant.none- ...

  8. oracle中游标详细用法

    转自:http://blog.csdn.net/liyong199012/article/details/8948952 游标的概念:     游标是SQL的一个内存工作区,由系统或用户以变量的形式定 ...

  9. oracle中merge的用法,以及各版本的区别 Create

    Merge是一个非常有用的功能,类似于Mysql里的insert into on duplicate key. Oracle在9i引入了merge命令,通过这个merge你能够在一个SQL语句中对一个 ...

随机推荐

  1. sizeof注意

    1.sizeof用于获取非托管类型的大小(以字节为单位). 非托管类型包括下表列出的内置类型以及以下类型: 枚举类型 指针类型 用户定义的结构,不包含任何属于引用类型的字段或属性     struct ...

  2. bzoj3638

    费用流+线段树 看见这个题我们马上就能想到费用流,设立源汇,分别向每个点连接容量为1费用为0的边,然后相邻的点之间连边,费用为点权,跑费用流就行了,但是很明显这样会超时,那么我们要优化一下,我们观察费 ...

  3. Python.h:No such file or directory

    出现No such file or directory的错误,有两种情况,一种是真的没有Python.h这个文件,一种是Python的版本不对, 可以进入/usr/include/文件夹下的Pytho ...

  4. linq to EF分组查询 group by 的使用

    第一种:查询表达式语法: IQueryable<EnrollmentDateGroup> data = from student in db.Students group student ...

  5. 5950 Recursive sequence (矩阵快速幂)

    题意:递推公式 Fn = Fn-1 + 2 * Fn-2 + n*n,让求 Fn; 析:很明显的矩阵快速幂,因为这个很像Fibonacci数列,所以我们考虑是矩阵,然后我们进行推公式,因为这样我们是无 ...

  6. Gym 100531A Alarm Clock (水题)

    题意:给定一个被高亮的数,问你是不是有个时间恰好高亮是这个数. 析:直接暴力,直接暴力,枚举每一位时间,当然也可以枚举时间,能找到就是有,找不到就算了. 代码如下: #pragma comment(l ...

  7. 利用OneDNS同步chrome数据

    将DNS服务器改成OneDNS的 117.50.11.11 备用改为 117.50.22.22 然后刷新自己的DNS缓存,接着测试一下https://test.onedns.net即可 这样既可以正常 ...

  8. JAVA大数处理(BigInteger,BigDecimal)

    原文链接 Java中有两个类BigInteger和BigDecimal分别表示大整数类和大浮点数类. 这两个类都在java.math.*包中,因此每次必须在开头处引用该包. Ⅰ基本函数: 1.valu ...

  9. How many Fibs? POJ - 2413

    How many Fibs? POJ - 2413 高精模板 #include<cstdio> #include<cstring> #include<algorithm& ...

  10. AJPFX讲解java单例模式

    单例设计模式概述:      单例模式就是要确保类在内存中只有一个对象,该实例必须自动创建,并且对外提供单例模式有以下特点: 1.单例类只能有一个实例. 2.单例类必须自己自己创建自己的唯一实例. 3 ...