ORACLE动态SQL语句
問題的提出
我們經常需要運行可變化的SQL語句,這種通常稱為動態SQL,在ORACLE中執行動態的SQL語句,需要了解ORACLE的動態SQL語句的相關規定。
SQL動態語句是由程序或者存儲過程生成的SQL語句,這種語句的特點是,不能簡單的去運行。因為它不是標準的,其中含有變化的成分,因此ORACLE提供了一個執行動態SQL語句的模式:
EXECUTE IMMEDIATE
這句話的含義是立即執行,而不先去進行語法檢查,在執行過程中可能會發生邏輯錯誤,則通過錯誤中斷進行處理。
一種動態SQL的方法
/***DBMS_OUTPUT.PUT_LINE(uSQL);p_Money_TJCALL p_Money_TJ();測試在SQL*PLUS下進行VAR r refcursor;Exec p_Money_TJ(:r);print r; ***/ CREATE OR REPLACE PROCEDURE p_Money_TJ(p_cur out sys_refcursor) AS-- 變量定義Cursor CC IS SELECT FTYPE FROM APP_MONEY GROUP BY FTYPE; uSQL VARCHAR2(32600); BEGINuSQL := 'BEGIN OPEN :p_cur for ';uSQL := uSQL || 'SELECT FMID 會員賬號,F_GETXM(FMID) 會員姓名';FOR C IN CC LOOPuSQL := uSQL || ',SUM(CASE WHEN FTYPE = '''||C.FTYPE||''' THEN FMONEY END) '||C.FTYPE;END LOOP;uSQL := uSQL || ' FROM APP_MONEY GROUP BY FMID';uSQL := uSQL || '; END;';EXECUTE IMMEDIATE uSQL USING p_cur; END;使用動態游標
1、聲明動態游標
TYPE cc_type IS REF CURSOR;2、聲明游標變量
my_cursor cc_type;3、使用游標
n_deptno:=20; uSQL := 'SELECT empno,ename FROM emp WHERE deptno = '||n_deptno; OPEN my_cursor FOR uSQL; LOOP FETCH my_cursor INTO n_empno,v_ename;EXIT WHEN my_cursor%NOTFOUND;--用n_empno,v_ename做其它處理--.... END LOOP; CLOSE my_cursor;4、小結
動態游標可以勝任大多數動態SQL的需求了,使用簡潔方便。
使用 EXECUTE IMMEDIATE
最早大家都使用DBMS_SQL包,但是太太麻煩了,最終都放棄了。但是自從有了EXECUTE IMMEDIATE之后,但要注意以下幾點:
EXECUTE IMMEDIATE代替了以前 Oracle8i 中 DBMS SQL package包, 它解析并馬上執行動態的SQL語句或非運行時創建的PL/SQL塊。動態創建和執行SQL語句性能超前,EXECUTE IMMEDIATE的目標在于減小企業費用并獲得較高的性能,較之以前它相當容易編碼。盡管DBMS_SQL仍然可用,但是推薦使用EXECUTE IMMEDIATE,因為它獲的收益在包之上。
使用技巧
1. EXECUTE IMMEDIATE將不會提交一個DML事務執行,應該顯式提交如果通過EXECUTE IMMEDIATE處理DML命令,那么在完成以前需要顯式提交或者作為EXECUTE IMMEDIATE自己的一部分. 如果通過EXECUTE IMMEDIATE處理DDL命令,它提交所有以前改變的數據
2. 不支持返回多行的查詢,這種交互將用臨時表來存儲記錄(參照例子如下)或者用REF cursors.
3. 當執行SQL語句時,不要用分號,當執行PL/SQL塊時,在其尾部用分號.
4. 在Oracle手冊中,未詳細覆蓋這些功能。下面的例子展示了所有用到Execute immediate的可能方面.希望能給你帶來方便.
5. 對于Forms開發者,當在PL/SQL 8.0.6.3.版本中,Forms 6i不能使用此功能.
EXECUTE IMMEDIATE用法例子
1. 在PL/SQL運行DDL語句
beginexecute immediate 'set role all'; end;2. 給動態語句傳值(USING 子句)
declarel_depnam varchar2(20) := 'testing';l_loc varchar2(10) := 'Dubai'; beginexecute immediate 'insert into dept values (:1, :2, :3)'using 50, l_depnam, l_loc;commit; end;3. 從動態語句檢索值(INTO子句)
declarel_cnt varchar2(20); beginexecute immediate 'select count(1) from emp'into l_cnt;dbms_output.put_line(l_cnt); end;4. 動態調用例程
例程中用到的綁定變量參數必須指定參數類型.黓認為IN類型,其它類型必須顯式指定
declarel_routin varchar2(100) := 'gen2161.get_rowcnt';l_tblnam varchar2(20) := 'emp';l_cnt number;l_status varchar2(200); beginexecute immediate 'begin ' || l_routin || '(:2, :3, :4); end;'using in l_tblnam, out l_cnt, in out l_status;if l_status != 'OK' thendbms_output.put_line('error');end if; end;5. 將返回值傳遞到PL/SQL記錄類型
同樣也可用%rowtype變量
declaretype empdtlrec is record (empno number(4),ename varchar2(20),deptno number(2));empdtl empdtlrec; beginexecute immediate 'select empno, ename, deptno '||'from emp where empno = 7934'into empdtl; end;6. 傳遞并檢索值
INTO子句用在USING子句前
declarel_dept pls_integer := 20;l_nam varchar2(20);l_loc varchar2(20); beginexecute immediate 'select dname, loc from dept where deptno = :1'into l_nam, l_locusing l_dept ; end;7. 多行查詢選項
對此選項用insert語句填充臨時表,用臨時表進行進一步的處理,也可以用REF cursors糾正此缺憾.
declarel_sal pls_integer := 2000; beginexecute immediate 'insert into temp(empno, ename) ' ||' select empno, ename from emp ' ||' where sal > :1'using l_sal;commit; end;對于處理動態語句,EXECUTE IMMEDIATE比以前可能用到的更容易并且更高效.當意圖執行動態語句時,適當地處理異常更加重要.應該關注于捕獲所有可能的異常.
Oracle 動態SQL
Oracle 動態SQL有兩種寫法:用 DBMS_SQL 或 execute immediate,建議使用后者。試驗步驟如下:
1. DDL 和 DML
/*** DDL ***/ begin EXECUTE IMMEDIATE 'drop table temp_1'; EXECUTE IMMEDIATE 'create table temp_1(name varchar2(8))'; end; /*** DML ***/ declare v_1 varchar2(8); v_2 varchar2(10); str varchar2(50); begin v_1:='測試人員'; v_2:='北京'; str := 'INSERT INTO test (name ,address) VALUES (:1, :2)'; EXECUTE IMMEDIATE str USING v_1, v_2; commit; end;2. 返回單條結果
declare str varchar2(500); c_1 varchar2(10); r_1 test%rowtype; begin c_1:='測試人員'; str:='select * from test where name=:c WHERE ROWNUM=1'; execute immediate str into r_1 using c_1; DBMS_OUTPUT.PUT_LINE(R_1.NAME||R_1.ADDRESS); end ;3. 返回結果集
CREATE OR REPLACE package pkg_test as /* 定義ref cursor類型 不加return類型,為弱類型,允許動態sql查詢, 否則為強類型,無法使用動態sql查詢; */ type myrctype is ref cursor; --函數申明 function get(intID number) return myrctype; end pkg_test; / CREATE OR REPLACE package body pkg_test as --函數體 function get(intID number) return myrctype is rc myrctype; --定義ref cursor變量 sqlstr varchar2(500); begin if intID=0 then --靜態測試,直接用select語句直接返回結果 open rc for select id,name,sex,address,postcode,birthday from student; else --動態sql賦值,用:w_id來申明該變量從外部獲得 sqlstr := 'select id,name,sex,address,postcode,birthday from student where id=:w_id'; --動態測試,用sqlstr字符串返回結果,用using關鍵詞傳遞參數 open rc for sqlstr using intid; end if; return rc; end get; end pkg_test;總結
以上是生活随笔為你收集整理的ORACLE动态SQL语句的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: win10 安装dig工具与使用dig命
- 下一篇: 【JAVA】java代码实现print2