首先在這裡發發牢騷,指責下那些刻板的書寫方式,不考慮讀者理不理解,感覺就是給專業人員用來複慣用的一樣,沒有前戲,直接就高潮,實在受不了!沒基礎或基礎差的完全不知道發生了什麼,一臉懵逼的看著,一星差評!!! execute immediate 以下引用介紹比較好的例子說明 看了上面的代碼,是否覺得理解 ...
首先在這裡發發牢騷,指責下那些刻板的書寫方式,不考慮讀者理不理解,感覺就是給專業人員用來複慣用的一樣,沒有前戲,直接就高潮,實在受不了!沒基礎或基礎差的完全不知道發生了什麼,一臉懵逼的看著,一星差評!!!
execute immediate
以下引用介紹比較好的例子說明
create or replace procedure proc_test(
--參數區域
)
is
--變數區域
--sql腳本
v_sql varchar2(2000) :='';
--記錄學生數量
v_num number;
begin
--執行區域
-- execute immediate用法1:立刻執行sql語句
v_sql := 'create or replace view myview as select id,name from student';
execute immediate v_sql;
--- execute immediate用法2:立刻執行sql語句,並賦值給某個變數
v_sql := 'select count(1) from student';
execute immediate v_sql into v_num;
-- execute immediate用法3:帶參數的sql
v_sql:='select * from student t where t.name=:1 and t.age=:2';
execute immediate v_sql using 'ZhangSan',23;
end proc_test;
/
看了上面的代碼,是否覺得理解?NO,NO,NO
對execute immediate 的解釋如下:
簡單來說 就是你一個存儲過程當中 創建了一個表 table_a 然後要用insert into將其他的數據插入到這個table_a當中,但是因為你在創建過程的時候 table_a還不存在,過程就會顯示有編譯錯誤,因為table_a不存在必然導致過程無法執行,所以無法編譯成功,而把insert into語句加如到 execute immediate之後 則oracle不會再去理會這個對象是否存在,因此可以成功編譯和執行。
看完了,估計還會有小朋友舉手問,跟動態有什麼關係,為何扯上動態,哪裡動態了,能不能講明白,等等。。。
敲黑板,人家說的動態,是說execute immediate後面跟的SQL代碼不固定,你想寫就寫啥,動態的!
然後又有小朋友,站起來了,你呀的,胡我啊,說最後代碼,隨便寫,我都想笑,這個跟直接寫SQL代碼,不要前面的execute immediate有什麼區別?不都執行那條語句麽?
哈哈,小朋友你坐下別激動,你問到點上了,execute immediate後邊SQL代碼要用一對單引號的(即' '),而直接寫SQL沒有的對吧,告訴你動態的秘訣就在於execute immediate後邊SQL代碼可以去拼接,這就實現了所謂動態,會根據不同情況,拼接不同的代碼。
簡單舉例
直接寫的 select * from dual;
用execute immediate寫 v_sql:='select * from dual'; EXECUTE IMMEDIATE v_sql; 一般來說直接寫SQL的性能是高於拼字元串的,因為如果執行拼字元串的需要內部自動調動oracle機制,先解析字元串映射成SQL語句然後再執行。 但是拼SQL的方式有好處。即SQL語句是一個字元串可以動態拼接,根據不同的條件來改變SQL語句,這是直接寫SQL所不能達到的。 拼SQL還有個好處就是 v_sql:='select * from tables t where t.c_date=:1 and t.name=:2'; EXECUTE IMMEDIATE v_sql USING '20130304','xiaoming'; 可以動態的對參數傳遞值,這是最大的優勢。 語法結構:EXECUTE IMMEDIATE dynamic_string
[INTO {define_variable[,define_variable]…| record}]
[USING [IN | OUT | IN OUT] bind_argument[,[IN | OUT \ IN OUT] bind_argumnet]…]
[{RETURNING | RETURN} INTO bind_argument[,bind_argument]…];
本地動態SQL語句一個優點是可以在代碼中是使用綁定變數。
先說說綁定變數 ":"稱綁定變數指示符,解釋如下:
它是用戶放入查詢中的占位符,它會告訴Oracle" 現在生成一個方案框架,實際執行語句的時候,會提供應該使用的實際值"。
例子如下:
select * from emp where dep='sale' ; //不使用綁定變數
select * from emp where dep=:sale //使用綁定變數
用法
處理DDL操作(CREATE,ALTER,DROP)
CREATE OR REPLACE PROCEDURE drop_table(table_name VARCHAR2)
IS
Sql_statemet VARCHAR2(100);
BEGIN
Sql_statement:=’DROP TABLE’ || table_name;
EXECUTE IMMEDIATE sql_statement;
END;
/
建立過程drop_table後,調用如下:
SQL> exec drop_table(‘worker’)
處理DCL操作(GRANT REVOKE)
SQL> conn system/manager
CREATE OR REPLACE PROCEDURE grant_sys_priv(priv VARCHAR2,username VARCHAR2)
IS
Sql_stat VARCHAR2(100);
BEGIN
Sql_stat:=’GRANT “ || priv|| ’ TO ’|| username;
EXECUTE IMMEDIATE sql_stat;
END;
/
調用
SQL> exec grant_sys_priv(‘CREATE SESSION’,’SCOTT’)
處理DML操作(INSERT UPDATE DELETE)
如果DML語句帶有占位符,那麼在E I語句中則要帶USING子句
如果DML語句帶有RETURNING子句,那麼E I語句中要帶有RETURNINGINTO子句
例子,處理單行查詢:
DECLARE
sql_stat VARCHAR2(100);
emp_record tbl%ROWTYPE;
BEGIN
sql-stat:='SELECT * FROM tbl WHERE tblno=:no';
EXECUTE IMMEDIATE sql_stat INTO emp_record USING &1;
dbms_output.put_line(emp_record.ename||emp_record.sal);
END;
EXECUTE IMMEDIATE -- 用法例子
1. 在PL/SQL運行DDL語句
begin
execute immediate 'set role all';
end;
2. 給動態語句傳值(USING 子句)
declare
l_depnam varchar2(20) := 'testing';
l_loc varchar2(10) := 'Dubai';
begin
execute immediate 'insert into dept values (:1, :2, :3)'
using 50, l_depnam, l_loc;
commit;
end;
3. 從動態語句檢索值(INTO子句)
declare
l_cnt varchar2(20);
begin
execute immediate 'select count(1) from emp'
into l_cnt;
dbms_output.put_line(l_cnt);
end;
4. 動態調用常式.常式中用到的綁定變數參數必須指定參數類型.
黓認為IN類型,其它類型必須顯式指定
declare
l_routin varchar2(100) := 'gen2161.get_rowcnt';
l_tblnam varchar2(20) := 'emp';
l_cnt number;
l_status varchar2(200);
begin
execute immediate 'begin ' || l_routin || '(:2, :3, :4); end;'
using in l_tblnam, out l_cnt, in out l_status;
if l_status != 'OK' then
dbms_output.put_line('error');
end if;
end;
5. 將返回值傳遞到PL/SQL記錄類型;同樣也可用%rowtype變數
declare
type empdtlrec is record (empno number(4),
ename varchar2(20),
deptno number(2));
empdtl empdtlrec;
begin
execute immediate 'select empno, ename, deptno ' ||
'from emp where empno = 7934'
into empdtl;
end;
6. 傳遞並檢索值.INTO子句用在USING子句前
declare
l_dept pls_integer := 20;
l_nam varchar2(20);
l_loc varchar2(20);
begin
execute immediate 'select dname, loc from dept where deptno = :1'
into l_nam, l_loc
using l_dept ;
end;
7. 多行查詢選項.對此選項用insert語句填充臨時表,
用臨時表進行進一步的處理,也可以用REF cursors糾正此缺憾.
declare
l_sal pls_integer := 2000;
begin
execute immediate 'insert into temp(empno, ename) ' ||
' select empno, ename from emp ' ||
' where sal > :1'
using l_sal;
commit;
end;