ORACLE 動態語句

2021-05-09 16:22:41 字數 4147 閱讀 6736

在一般的pl/sql程式開發中,可以使用sql的dml語句和事務控制語句,但是ddl語句及會話語句卻不能在pl/sql中直接使用,要想實現在pl/sql中使用ddl語句及會話控制語句,可以通過動態sql來實現。

所謂動態sql是指在pl/sql塊編譯時sql語句是不確定的,例如根據使用者輸入引數的不同而執行不同的操作。編譯程式對動態語句部分不進行處理,只是在程式執行時動態地建立語句,對語句進行語法分析並執行該語句。 oracle中的動態sql可以通過本地動態sql命令來執行,也可以通過dbms_sql程式包來執行。

通常在開發中用簡單的本地動態sql就能解決問題,在下面我會用別的方法來實現。給出執行本地動態sql的語法:

execute immediate dynamic_sql_string [into define_variable_list] [using bind_argument_list];

其中: dynamic_sql_string 是動態sql語句字串 into子句用於接受select語句選擇的紀錄值。 using子句用於接受繫結輸入引數變數。

例子1:

declare

sql_s varchar2(200);

emp_id number(4):=7566; 

emp_rec emp%rowtype;

begin

execute  immediate  'create  table  table_name (id number,amt  number)';  

sql_s:='select * from emp where empno=:id;

execute  immediate  sql_s into  emp_rec  using  emp_id;

end;

這段**首先執行一條建立的動態sql,接著執行了帶引數的select語句。execute immediate語句只能用於處理返回單行或沒有返回的sql語句,要處理返回多行的動態sql就要使用ref游標的open...for語句。下面就來討論:

例2:要求:使用者輸入多個批次號(lot_number)和物料號(key_number )或多個批次號(lot_number)和**商名(ver_apell)來求庫存中物料的數目為了讓**結構清晰,我使用包來建立**:

首先,建立包頭部分:

create  or  replace  package  smt_traceability_p    is

type s_s_qty is ref cursor;

procedure surplus_stock(key_number  in       sfism4.c_see_iqc_check_detail.key_part_no%type,

lot_number in varchar2,

ver_apell  in  sfism6.r_smt_inv_tran_t.ver%type,

su_st_qty out s_s_qty);

end smt_traceability_p;

接著,建立包體:

create  or  replace  package  body  smt_traceability_p   is

procedure surplus_stock(

key_number   in  sfism4.c_see_iqc_check_detail.key_part_no%type,

lot_number  in  varchar2,

ver_apell  in  sfism6.r_smt_inv_tran_t.ver%type,

su_st_qty out s_s_qty)   is 

cicd_qty number;

rsit_qty number;

v_sql varchar2(10000);

begin

if (key_number  is  null)  then

open  su_st_qty  for  select   0   from   dual;

elsif (ver_apell = 'nosupply'  and  lot_number  is  not  null) then

v_sql := 'select  (select   nvl(sum(cicd.qty),0)  

from  sfism4.c_see_iqc_check_detail   cicd   where  

cicd.key_part_no = ''' || ltrim(rtrim(key_number, ' '), ' ') || '''

and 

cicd.lot_no  in (' || lot_number || '))- (select   nvl(sum(rsit.qty),0)

from  sfism6.r_smt_inv_tran_t   rsit   where  

rsit.key_part_no = ''' || ltrim(rtrim(key_number, ' '), ' ') || '''

and rsit.lot_no   in  (' || lot_number || '))   from   dual';

open   su_st_qty   for    v_sql;

else

select     sum(cicd.qty)    into    cicd_qty    

from    sfism4.c_see_iqc_check_detail   cicd  

where    cicd.key_part_no = ltrim(rtrim(key_number, ' '), ' ')

and cicd.supply = ltrim(rtrim(ver_apell, ' '), ' ');

select    sum(rsit.qty)   into    rsit_qty    from  

sfism6.r_smt_inv_tran_t   rsit    where  

rsit.key_part_no = ltrim(rtrim(key_number, ' '), ' ') 

and     rsit.ver = ltrim(rtrim(ver_apell, ' '), ' ');

if  (cicd_qty is null)  then

cicd_qty := 0;

rsit_qty := 0;

/* elsif(rsit_qtyes is null) then rsit_qty:=0;*/

end if;

open   su_st_qty   for   select   cicd_qty  -  nvl(rsit_qty, 0)   re_num

from   dual;

end if;

end;

注釋:因為使用者會輸入乙個或多個批次號,並且輸入時的格式是固定的,每個批次號用單引號引起來,批次號和批次號之間用逗號隔開,即:

'1tob8311cjl',''rjc4633012/33'

請注意  rsit.lot_no   in  (' || lot_number || '))  這種寫法。如果使用者輸入是乙個批次號時,可以把上面那段動態sql寫成下面這種形式:

v_sql := 'select    (select     sum(cicd.qty)   

from   sfism4.c_see_iqc_check_detail   cicd   where

cicd.key_part_no  =  :  key_number   and   

cicd.lot_no   in  (:lot_number))- (select sum(rsit.qty)

from   sfism6.r_smt_inv_tran_t   rsit    where

rsit.key_part_no  =  : key_number   and    rsit.lot_no

in  ( : lot_number ))    from    dual ';

open    su_st_qty    for    v_sql    using

ey_number, lot_number, key_number, lot_number;

另外,儅需要對ref  cursor中的內容進行處理時,就需要使用fetch su_st_qty   into   variable_name或根據需求使用迴圈語句來進行處理。這裡就不進行介紹了。

Oracle動態SQL語句

在使用odp.net進行oracle程式設計時,有時候sql語句非常複雜,需要採用動態構造查詢語句的情況,有兩種方法可以構造動態的sql語句,並執行返回結果集。1 在資料訪問層構造sql語句 例如下面的語句,將構造完整的sql語句賦值給commandtext,再傳遞到資料庫進行執行,返回結果集。lo...

Oracle動態sql語句

在pl sql程式開發中,可以使用dml語句和事務控制語句,但是還有很多語句 比如ddl語句 不能直接在pl sql中執行。這些語句可以使用動態的sql來實現。動態sql是指在pl sql塊編譯sql語句是不確定的。動態sql執行ddl語句 drop procedure procedure5 cre...

ORACLE 動態執行SQL語句

oracle 動態sql oracle 動態sql有兩種寫法 用 dbms sql 或 execute immediate,建議使用後者。試驗步驟如下 1.ddl 和 dml ddl begin execute immediate drop table temp 1 execute immediat...