在一般的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...