動態SQL簡介: 1、靜態SQL 靜態SQL是指直接嵌入在PL/SQL塊中的SQL語句。在編寫PL/SQL時。靜態SQL用于完成特定或固定的任務: 2、動態SQL 動態SQL是指在運行PL/SQL塊時動態輸入的SQL語句。如果在PL/SQL中需要執行DDL語句,DCL語句(GRANT,REVOKE),或者在PL/SQL中需要執行更加靈活的SQL語句(例如在SELECT語句中使用不同的WHERE條件),那么就必須使用動態SQL。 在PL/SQL塊中編寫動態語句時,需要將SQL語句存放在字符創變量中,而且SQL語句可以包含占位符(以冒號開始)。 如:CREATE TABLE temp(cola INT,colb VARCHAR2(10)) GRANT SELECT ON temp TO smith DELETE FROM emp WHERE sal>:a SELECT ename,sal FROM emp WHERE empno=:l 3、動態SQL的處理方法 (1)、使用EXECUTE IMMEDIATE 不能用于處理多行查詢語句。 (2)、使用OPEN-FOR FETCH 和CLOSE語句 為了處理動態的多行查詢操作,必須使用OPEN-FOR語句打開游標,使用FETCH 語句提取循環數據,最終使用CLOSE語句關閉游標. (3)、使用批量動態SQL
處理非查詢語句 為了動態的處理非查詢語句(DML DDL DCL)或者單行查詢語句,可以在PL/SQL快中使用EXEXUTE IMMEDIATE 語句, EXECUTE IMMEDIATE dynamic_string [INTO |define_variable|,define_variable...|record] [USING [IN|OUT|INOUT] bind_argument...] [{RETURNING|RETURN} INTO bind_argument...]; dynamic_string 用于指定存放SQL語句或者PL/SQL塊的字符串變量; define_variable用于指定存放單行查詢結婚的變量 輸入bind_argument(IN)用于指定存放被傳遞給動態SQL值的變量 輸出bind_argument(OUT)用于指定存放動態SQL返回值的變量 1、使用EXECUTE IMMEDIATE 處理DDL操作 EXECUTE IMMEDIATE后面只需要帶有DDL語句文本即可,而不需要INTO和USING 字句。 CREATE OR REPLACE PROCEDURE drop_table(table_name VARCHAR2) IS sql_statement VARCHAR2(100); BEGIN sql_statement:='DROP TABLE '||table_name; EXECUTE IMMEDIATE sql_statement; END; 2、使用EXECUTE IMMEDIATE 處理DCL操作 和處理DDL語句差不多 3、使用EXECUTE IMMEDIATE 處理DML 語句 如果DML語句既沒有占位符,也咩有RETURNING 字句,那么在EXECUTE IMMEDIATE 語句之后不需要帶有USING和RETURNING INTO子句; 如果DML語句含有占位符,那么在 EXECUTE IMMEDIATE 語句之后要帶有USING子句; 如果DML語句之后帶有RETURNING子句,那么在EXECUTE IMMEDIATE 語句之后帶有RETURNING INTO子句。 (1)、處理無占位符和RETURNING子句的DML語句 DECLARE sql_statement VARCHAR2(100); BEGIN sql_statement:='UPDATE emp SET sal=sal*1.1 WHERE depno=30'; EXECUTE IMMEDIATE sql_statement; END; (2)、處理包含占位符的DML語句 要使用USING 自己為占位符提供輸入數據。 DECLARE sql_state VARCHAR2(100); BEGIN sql_state:='UPDATE emp SET sal=sal*(1+:percent/100) WHRE deptno=:dno'; EXECUTE IMMEDIATE sql_state USING &1,&2; END; (3)、處理包含RETURNING 子句的DML語句 必要要使用RETURNING INTO 子句接受返回數據。 注意:直接使用EXECUTE IMMEDIATE 語句處理帶有RETURNING 子句的DML語句時,只能處理作用在單行的DML語句。 如果DML語句作用在多行傷,則必須要使用BULK子句。 DECLARE salary NUMBER(6,2); sql_state VARCHAR2(100); BEGIN sql_state:='UPDATE emp SET sal=(sal*:present/100) WHERE empno=:eno RETURNING sal INTO :salary'; EXECUTE IMMEDIATE sql_state USING &1,&2 RETURNING INTO salary; dbms_output.put_line('新工資:'||salary); END; (4)、使用EXECUTE IMMEDIATE 處理單行查詢 要使用INTO 子句接受返回數據 DECLARE sql_state VARCHAR2(100); emp_record emp%ROWTYPE; BEGIN sql_state:='SELECT * FROM emp WHERE empno=:eno'; EXECUTE IMMEDIATE sql_state INTO emp_record USING &1; dbms_output.put_line('雇員:'||emp_record.ename||'的工資為:'||emp_record.sal); END;處理多行查詢語句: 使用EXECUTE IMMEDIATE只能處理單行查詢語句,為了動態的處理SELECT語句所返回的多行數據,需要使用OPEN-FOR,FETCH,CLOSE語句。 步驟如下 定義游標變量-->打開游標變量-->循環提取數據-->關閉游標變量。 1、定義游標變量: TYPE cursortype IS REF CURSOR; cursor_variable cursortype; 2、打來游標變量 OPEN cursor_variable FOR dynamic_string [USING bind_argument,...]; bind_argument 用于存放傳遞給動態SELECT語句值的變量。 3、循環提取數據 FETCH cursor_variable INTO {var1[,var2]...|record_var}; 4、關閉游標變量 close cursor_variable; 5、多行查詢實例: DECLARE TYPE cursor_type IS REF CURSOR; sql_state VARCHAR2(100); emp_record emp%ROWTYPE; v_cursor vursor_type; BEGIN sql_state:='SELECT * FROM emp WHERE deptno=:dno'; OPEN v_cursor FOR sql_state USING &deptno; LOOP FETCH v_cursor INTO emp_record; EXIT WHEN v_cursor%NOTFOUND; dbms_output.put_line('雇員名:'||emp_record.ename||'的工資是:'||emp_record.salary); END LOOP; CLOSE v_cursor; END;在動態SQL中使用BULK子句 Oracle9i新增加的特性。可以加快批量數據的處理速度。 有三種語句支持BULK子句:EXECUTE IMMEDIATE,FETCH和FORALL 1、在EXECUTE IMMEDIATE語句中使用動態BULK子句 EXECUTE IMMEDIATE dynamic_string [BULK COLLECT INTO |define_variable|,define_variable...|record] [USING [IN|OUT|INOUT] bind_argument...] [{RETURNING|RETURN} BULK COLLECT INTO bind_argument...]; (1)、使用BULK子句處理DML語句返回子句 DECLARE TYPE ename_table_type IS TABLE OF emp.ename%TYPE INDEX BY BINARY_INTEGER; TYPE sal_table_type IS TABLE OF emp.sal%TYPE INDEX BY BINARY_INTEGER; ename_table ename_table_type; sal_table sal_table_type; sql_state VARCHAR2(150); BEGIN sql_state:='UPDATE emp SET sal=sal*(1+:precent/100) WHERE deptno=:dno' ||'RETURNING ename,sal INTO :name,:salary'; EXECUTE IMMEDIATE sql_state USING &precent,&depno RETURNING BULK COLLECT INTO ename_table,sal_table ; FOR i IN 1..ename_table.COUNT LOOP dbms_output.put_line('雇員名:'||ename_table(i)||'的工資是:'||sal_table(i)); END LOOP; END; (2)、使用BULK子句處理多行查詢 DECLARE sql_state VARCHAR2(100); TYPE ename_table_type IS TABLE OF emp.ename%TYPE INDEX BY BINARY_INTEGER; ename_table ename_table_type; BEGIN sql_state:='SELECT ename FROM emp WHERE empno=:eno'; EXECUTE IMMEDIATE sql_state BULK COLLECT INTO emp_record USING &1; FOR i IN 1..ename_table.COUNT LOOP dbms_output.put_line('雇員:'||ename_table(i)); END LOOP; END; 2、在FETCH 語句中使用BULK子句 OPEN-FOR ,FETCH,CLOSE .....BULK DECLARE TYPE cursor_type IS REF CURSOR; TYPE ename_table_type IS TABLE OF emp.ename%TYPE INDEX BY BINARY_INTEGER; sql_state VARCHAR2(200); v_vursor cursor_type; ename_table ename_table_type; BEGIN sql_state:='SELECT ename FROM emp WHERE deptno=:dno'; OPEN v_corsor FOR sql_state USING &deptno; FETCH v_cursor BULK COLLECT INTO ename_table; FOR i IN i..ename_table.COUNT LOOP dbms_output.put_line('雇員:'||ename_table(i)); END LOOP; CLOSE v_cursor; END; FORALL
本文轉自:http://blog.csdn.net/memoordit/article/details/2385600?locationNum=5&fps=1
新聞熱點
疑難解答