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所提供定義語句db mssql.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系統包的過程當中,其方法簡單而又不失靈活,但仍是須要注意一些問題:
    一、在整個程序的設計過程當中,對遊標的操做切不可有省略的部分,一旦省略其中某一步驟,則會程序編譯過程既告失敗,如在程序結尾處未對改遊標進行關閉操做,則在再次調用過程時會出現錯誤.
    二、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 |
  --                      ------------ 
  --
  ---------------
相關文章
相關標籤/搜索