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塊時,在其尾部用分號. html
FOR I IN 0 .. 999 LOOP V_TABLENAME := 'YTEXP.T_EXP_WAYBILL_' || TO_CHAR(I, 'fm000'); V_SQL := 'UPDATE YTRPT.T_RPT_WAYBILL_OVERDUE O SET O.BILL_SOURCE_ORG_CODE = (SELECT W.MAT_ORG_CODE FROM ' || V_TABLENAME || ' W WHERE O.WAYBILL_NO = W.WAYBILL_NO), O.MAT_EXPIRE_TIME = (SELECT W.MAT_EXPIRE_TIME FROM ' || V_TABLENAME || ' W WHERE O.WAYBILL_NO = W.WAYBILL_NO) WHERE O.RPT_DATE = TO_DATE('' '|| TO_CHAR(START_TIME,'YYYY-MM-DD') ||' '',''YYYY-MM-DD'' ) AND O.BILL_SOURCE_ORG_CODE IS NULL '; EXECUTE IMMEDIATE V_SQL; commit; END LOOP;
EXECUTE IMMEDIATE -- 用法例子
1. 在PL/SQL運行DDL語句sql
Sql代碼 數據庫
begin
execute immediate 'set role all';
end;oracle
2. 給動態語句傳值(USING 子句)
Sql代碼框架
declare
l_depnam varchar2(20) := 'testing';
l_loc varchar2(10) := 'D?i';
begin
execute immediate 'insert into dept vals (:1, :2, :3)'
using 50, l_depnam, l_loc;
commit;
end;性能
3. 從動態語句檢索值(INTO子句)
Sql代碼 測試
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類型,其它類型必須顯式指定
Sql代碼 編碼
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;.net
if l_status != 'OK' then
dbms_output.put_line('error');
end if;
end;
5. 將返回值傳遞到PL/SQL記錄類型;一樣也可用%rowtype變量
Sql代碼
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子句前
Sql代碼
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糾正此缺憾.
Sql代碼
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;
對於處理動態語句,EXECUTE IMMEDIATE 比之前可能用到的更容易而且更高效.
當意圖執行動態語句時,適當地處理異常更加劇要.應該關注於捕獲全部可能的異常.15:40 | 添加評論 | 固定連接 | 寫入日誌 | SQLoracle中insert into select的用法
/* Formatted on 2008/06/02 15:37 (Formatter Plus v4.8.7) */
INSERT INTO t_work
(f_recid, f_jobid, f_ruleid, f_jobtype, f_operid, f_opername,
f_btime, f_assigntime, f_downtime, f_worktimes, f_finishtime)
SELECT SYS_GUID () AS f_recid, f_jobid, f_ruleid, f_jobtype, f_operid,
f_opername, f_btime, f_assigntime,f_downtime,
DECODE (f_downtime, null,1, f_downtime + 1) as f_worktimes,
TO_CHAR (SYSDATE, 'yyyy-MM-dd hh:mm:ss') AS finishtime
FROM t_bfer
WHERE f_jobid = '21'
說明將t_bfer中的一條記錄添加到t_work表中。
其中b_bfer中沒有的列有f_recid和t_finishtime;
f_worktimes須要加1。
SYS_GUID()的意思是生成一個32位的永不重複的字符串。
DECODE(f_downtime, null,1, f_downtime + 1)的意思是若是f_downtime爲空(null)獲得的值爲1,不然爲f_downtime+1。
TO_CHAR(SYSDATE, 'yyyy-MM-dd hh:mm:ss')爲格式化時間格式;在表t_work中f_finishtime的數據類型爲varchar2.
15:22 | 添加評論 | 固定連接 | 寫入日誌 | SQLPL/SQL開發中動態SQL的使用方法
原文來自:http://blog.chinaunix.net/u/19673/showart_272022.html
通常的PL/SQL程序設計中,在DML和事務控制的語句中能夠直接使用SQL,可是DDL語句及系統控制語句卻不能在PL/SQL中直接使用,要想實如今PL/SQL中使用DDL語句及系統控制語句,能夠經過使用動態SQL來實現。
首先咱們應該瞭解什麼是動態SQL,在Oracle數據庫開發PL/SQL塊中咱們使用的SQL分爲:靜態SQL語句和動態SQL語句。所謂靜態SQL 指在PL/SQL塊中使用的SQL語句在編譯時是明確的,執行的是肯定對象。而動態SQL是指在PL/SQL塊編譯時SQL語句是不肯定的,如根據用戶輸 入的參數的不一樣而執行不一樣的操做。編譯程序對動態語句部分不進行處理,只是在程序運行時動態地建立語句、對語句進行語法分析並執行該語句。
Oracle中動態SQL能夠經過本地動態SQL來執行,也能夠經過DBMS_SQL包來執行。下面就這兩種狀況分別進行說明:
1、本地動態SQL
本地動態SQL是使用EXECUTE IMMEDIATE語句來實現的。
一、本地動態SQL執行DDL語句:
需求:根據用戶輸入的表名及字段名等參數動態建表。
create or replace procedure proc_test
(
table_name in varchar2, --表名
field1 in varchar2, --字段名
datatype1 in varchar2, --字段類型
field2 in varchar2, --字段名
datatype2 in varchar2 --字段類型
) as
str_sql varchar2(500);
begin
str_sql:=’create table ’||table_name||’(’||field1||’ ’||datatype1||’,’||field2||’ ’||datatype2||’)’;
execute immediate str_sql; --動態執行DDL語句
exception
when others then
null;
end ;
以上是編譯經過的存儲過程代碼。下面執行存儲過程動態建表。
SQL> execute proc_test(’dinya_test’,’id’,’number(8) not null’,’name’,’varchar2(100)’);
PL/SQL procedure s?ssfully completed
SQL> desc dinya_test;
Name Type Nullable Default Comments
---- ------------- -------- ------- --------
ID NUMBER(8)
NAME VARCHAR2(100) Y
SQL>
到這裏,就實現了咱們的需求,使用本地動態SQL根據用戶輸入的表名及字段名、字段類型等參數來實現動態執行DDL語句。
二、本地動態SQL執行DML語句。
需求:將用戶輸入的值插入到上例中建好的dinya_test表中。
create or replace procedure proc_insert
(
id in number, --輸入序號
name in varchar2 --輸入姓名
) as
str_sql varchar2(500);
begin
str_sql:=’insert into dinya_test vals(:1,:2)’;
execute immediate str_sql using id,name; --動態執行插入操做
exception
when others then
null;
end ;
執行存儲過程,插入數據到測試表中。
SQL> execute proc_insert(1,’dinya’);
PL/SQL procedure s?ssfully completed
SQL> select * from dinya_test;
ID NAME
1 dinya
在上例中,本地動態SQL執行DML語句時使用了using子句,按順序將輸入的值綁定到變量,若是須要輸出參數,能夠在執行動態SQL的時候,使用RETURNING INTO 子句,如:
declare
p_id number:=1;
v_count number;
begin
v_string:=’select count(*) from table_name a where a.id=:id’;
execute immediate v_string into v_count using p_id;
end ;
更多的關於動態SQL中關於返回值及爲輸出輸入綁定變量執行參數模式的問題,請讀者自行作測試。
2、使用DBMS_SQL包
使用DBMS_SQL包實現動態SQL的步驟以下:A、先將要執行的SQL語句或一個語句塊放到一個字符串變量中。B、使用DBMS_SQL包的 parse過程來分析該字符串。C、使用DBMS_SQL包的bind_variable過程來綁定變量。D、使用DBMS_SQL包的execute函 數來執行語句。
一、使用DBMS_SQL包執行DDL語句
需求:使用DBMS_SQL包根據用戶輸入的表名、字段名及字段類型建表。
create or replace procedure proc_dbms_sql
(
table_name in varchar2, --表名
field_name1 in varchar2, --字段名
datatype1 in varchar2, --字段類型
field_name2 in varchar2, --字段名
datatype2 in varchar2 --字段類型
)as
v_cursor number; --定義光標
v_string varchar2(200); --定義字符串變量
v_row number; --行數
begin
v_cursor:=dbms_sql.open_cursor; --爲處理打開光標
v_string:=’create table ’||table_name||’(’||field_name1||’ ’||datatype1||’,’||field_name2||’ ’||datatype2||’)’;
dbms_sql.parse(v_cursor,v_string,dbms_sql.native); --分析語句
v_row:=dbms_sql.execute(v_cursor); --執行語句
dbms_sql.close_cursor(v_cursor); --關閉光標
exception
when others then
dbms_sql.close_cursor(v_cursor); --關閉光標
raise;
end;
以上過程編譯經過後,執行過程建立表結構:
SQL> execute proc_dbms_sql(’dinya_test2’,’id’,’number(8) not null’,’name’,’varchar2(100)’);
PL/SQL procedure s?ssfully completed
SQL> desc dinya_test2;
Name Type Nullable Default Comments
---- ------------- -------- ------- --------
ID NUMBER(8)
NAME VARCHAR2(100) Y
SQL>
二、使用DBMS_SQL包執行DML語句
需求:使用DBMS_SQL包根據用戶輸入的值更新表中相對應的記錄。
查看錶中已有記錄:
SQL> select * from dinya_test2;
ID NAME
1 Oracle
2 CSDN
3 ERP
SQL>
建存儲過程,並編譯經過:
create or replace procedure proc_dbms_sql_update
(
id number,
name varchar2
)as
v_cursor number; --定義光標
v_string varchar2(200); --字符串變量
v_row number; --行數
begin
v_cursor:=dbms_sql.open_cursor; --爲處理打開光標
v_string:=’update dinya_test2 a set a.name=:p_name where a.id=:p_id’;
dbms_sql.parse(v_cursor,v_string,dbms_sql.native); --分析語句
dbms_sql.bind_variable(v_cursor,’:p_name’,name); --綁定變量
dbms_sql.bind_variable(v_cursor,’:p_id’,id); --綁定變量
v_row:=dbms_sql.execute(v_cursor); --執行動態SQL
dbms_sql.close_cursor(v_cursor); --關閉光標
exception
when others then
dbms_sql.close_cursor(v_cursor); --關閉光標
raise;
end;
執行過程,根據用戶輸入的參數更新表中的數據:
SQL> execute proc_dbms_sql_update(2,’csdn_dinya’);
PL/SQL procedure s?ssfully completed
SQL> select * from dinya_test2;
ID NAME
1 Oracle
2 csdn_dinya
3 ERP
SQL>
執行過程後將第二條的name字段的數據更新爲新值csdn_dinya。這樣就完成了使用dbms_sql包來執行DML語句的功能。
使用DBMS_SQL中,若是要執行的動態語句不是查詢語句,使用DBMS_SQL.Execute或 DBMS_SQL.Variable_Val來執行,若是要執行動態語句是查詢語句,則要使用DBMS_SQL.define_column定義輸出變 量,而後使用DBMS_SQL.Execute, DBMS_SQL.Fetch_Rows, DBMS_SQL.Column_Val及DBMS_SQL.Variable_Val來執行查詢並獲得結果。
PLSQL中 EXECUTE IMMEDIATE語句 先說說綁定變量 ":"稱綁定變量指示符,解釋以下: 它是用戶放入查詢中的佔位符,它會告訴Oracle" 如今生成一個方案框架,實際執 行語句的時候,會提供應該使用的實際值"。 例子以下: select * from emp where dep='sale'; //不使用綁定變量 select * from emp where dep=:sale //使用綁定變量 通常在 procedure or function 中使用,能夠優化共享池的使用。 兩句的區別很明顯,後者多一個佔位符,這個以冒號開始的變量能夠靈活地執行不 同條件的where語句,這是動態SQL語句。 一、 語法: 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 bing_argument[,bind_argument]…]; 二、 用法 處理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;