Oracle PL/SQL (12) - 動(dòng)態(tài)SQL語(yǔ)句

1.靜態(tài)SQL與動(dòng)態(tài)SQL
Oracle編譯PL/SQL程序塊分為兩個(gè)種:一種是,SQL語(yǔ)句在程序編譯期間就已經(jīng)確定,大多數(shù)的編譯情況屬于這種類(lèi)型,如:靜態(tài)SQL;另外一種是SQL語(yǔ)句只有在運(yùn)行階段才能建立,例如當(dāng)查詢條件為用戶輸入時(shí),那么Oracle的SQL引擎就無(wú)法在編譯期對(duì)該程序語(yǔ)句進(jìn)行確定,只能在用戶輸入一定的查詢條件后才能提交給SQL引擎進(jìn)行處理。如:動(dòng)態(tài)SQL。
本文主要就動(dòng)態(tài)SQL的基礎(chǔ)做總結(jié)。

2.使用EXECUTE IMMEDIATE語(yǔ)句處理相關(guān)語(yǔ)句:
動(dòng)態(tài)SQL是一種”不確定”的SQL,那其執(zhí)行就有其相應(yīng)的特點(diǎn)。Oracle中提供了Execute immediate語(yǔ)句來(lái)執(zhí)行動(dòng)態(tài)SQL,語(yǔ)法如下:

Excute immediate 動(dòng)態(tài)SQL語(yǔ)句 using 綁定參數(shù)列表 returning into 輸出參數(shù)列表;
  1. USING 子句給動(dòng)態(tài)語(yǔ)句傳值
    例如:
declare 
  l_str1 varchar2(20) := 'hello'; 
  l_str2    varchar2(10) := 'world'; 
  begin 
  execute immediate 'insert into t_str values   (:1, :2, :3)' 
   using 50, l_str1 , l_str2 ; 
 commit;   -----一定要顯示提交
end; 

4.INTO子句從動(dòng)態(tài)語(yǔ)句檢索值
例如:

declare 
 v_cnt    varchar2(20); 
begin 
  execute immediate 'select count(1) from emp'  into v_cnt    ; 
 dbms_output.put_line(v_cnt ); 
end; 

5.傳遞并檢索值.INTO子句用在USING子句前
例如:

declare 
 v_empno    pls_integer := 20; 
 v_ename     varchar2(20); 
 v_esex     varchar2(20); 
begin 
  execute immediate 'select ename, esex from emp where empno = :1' 
   into v_ename,v_esex 
   using v_empno   ; 
end; 

6.輸出參數(shù)returning into 子句用在USING子句后
例如:

create or replace procedure update_data(stuid varchar2, age number)
as
   strSQL varchar2(1000);
   strID varchar2(50);
   strName varchar2(50);
   strSex varchar2(50);
begin
   strSQL := 'update tb_student set age=:a where id=:b returning id, name, sex into :c, :d, :e';
   execute immediate strSQL using age, stuid returning into strID, strName, strSex;
   execute immediate 'commit'; -- 這樣也是可以的
   dbms_output.put_line('ID:' || strID || ' ;Name:' || strName || ' ;Sex:' || strSex);
end;

在上面的代碼中,:a、:b、:c、:d和:e都是占位符,占位符必須以冒號(hào)開(kāi)始,名字無(wú)所謂。使用了占位符以后,就需要在execute immediate語(yǔ)句后面使用using將參數(shù)傳遞進(jìn)去,參數(shù)將與占位符一一對(duì)應(yīng)。但是有一點(diǎn)需要謹(jǐn)記,綁定參數(shù)不能是表名、列名、數(shù)據(jù)類(lèi)型等,綁定參數(shù)只能是值、變量或者表達(dá)式。用DDL語(yǔ)句動(dòng)態(tài)創(chuàng)建對(duì)象時(shí),應(yīng)該使用連接運(yùn)算符||,最好不要使用綁定參數(shù)。
另外上述代碼中還使用了一個(gè)returning into的關(guān)鍵語(yǔ)句,returning into語(yǔ)句的主要作用是:
delete操作:returning返回的是delete之前的結(jié)果
insert操作:returning返回的是insert之后的結(jié)果
update操作:returning語(yǔ)句是返回update之后的結(jié)果

7.通過(guò)游標(biāo)實(shí)現(xiàn)多行查詢的SELECT語(yǔ)句
例如:

declare
  type ref_cur is ref cursor;
  rc ref_cur;
  seriesrow t_Md_Vehicle_Series%rowtype;
  v_sql varchar2(500):='select * from t_Md_Vehicle_Series m where m.vehicle_make_id=:makeid';
  v_sql2 varchar2(500);
  type tb_model_type is table of t_md_vehicle_model%rowtype;
   model_array tb_model_type;
begin
 DBMS_OUTPUT.ENABLE(100000);

  open rc for v_sql using 'CN001';
  loop
     FETCH rc INTO seriesrow;
       EXIT WHEN rc%NOTFOUND;
       dbms_output.put_line('name:'||seriesrow.vehicle_series_name||'-------------->  id:'||seriesrow.vehicle_series_id);
       v_sql2:='select * from t_md_vehicle_model m where m.vehicle_series_id=:seriesid and m.valid_flag=1'; 
       execute immediate v_sql2 bulk collect into model_array using seriesrow.vehicle_series_id;
       for i in model_array.first .. model_array.last loop
       dbms_output.put_line('ID:' || model_array(i).vehicle_sub_model_id 
                           || '-------------->  Name:' || model_array(i).vehicle_sub_model_name  );
   end loop;
  end loop;
  CLOSE rc;
end;

輸出結(jié)果:


image.png

上述語(yǔ)句中,用帶有子句bulk collect into的execute immediate語(yǔ)句。采用bulk collect into可以將查詢結(jié)果一次性地加載到集合中,可以在select into、fetch into、returning into語(yǔ)句中使用bulk collect into;但是需要特別注意的是,在使用bulk collect into時(shí),所有的into變量都必須是集合類(lèi)型。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容