FORALL執行UPDATE語句
在ITPUB上看到一個FORALL執行UPDATE的帖子,覺得有點意思,簡單記錄一下。
原帖地址:http://www.itpub.net/thread-1443896-1-1.html
FOR ALL語法淺析:http://yangtingkun.itpub.net/post/468/198828
以前研究過FORALL中的INSERT語句,發現語句透過繫結陣列的方式,實現了批次繫結,一次執行的方式,從而提高了執行的效率。
但是對於UPDATE語句而言,Oracle的實現和INSERT是不同的:
SQL> CREATE TABLE T AS SELECT ROWNUM ID FROM TAB;
表已建立。
SQL> SELECT * FROM T;
ID
----------
1
2
3
4
5
6
已選擇6行。
SQL>
DECLARE
2
TYPE T_ID IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
3
V_ID T_ID;
4
BEGIN
5
SELECT ID
6
BULK COLLECT INTO V_ID
7
FROM T;
8
FORALL I IN V_ID.FIRST..V_ID.LAST
9
UPDATE T
10
SET ID = V_ID(I);
11
END;
12
/
PL/SQL 過程已成功完成。
SQL> SELECT * FROM T;
ID
----------
6
6
6
6
6
6
已選擇6行。
SQL> ROLLBACK;
回退已完成。
結果並不像想象中的,仍然是123456,而是所有的記錄都被更新為6。顯然Oracle不太可能只使用陣列變數在中最後一個值進行更新,因此T表中的記錄應該是被更新了6次,所以對於UPDATE語句而言,繫結陣列中有多少個值,更新就執行了多少次,而對於當前沒有指定WHERE條件,所以每次執行的時候所有的記錄都被更新。
正確的寫法類似於:
SQL>
DECLARE
2
TYPE T_ID IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
3
V_ID T_ID;
4
BEGIN
5
SELECT ID
6
BULK COLLECT INTO V_ID
7
FROM T;
8
FORALL I IN V_ID.FIRST..V_ID.LAST
9
UPDATE T
10
SET ID = V_ID(I)
11
WHERE ID = V_ID(I);
12
END;
13
/
PL/SQL 過程已成功完成。
SQL> SELECT * FROM T;
ID
----------
1
2
3
4
5
6
已選擇6行。
下面驗證一下剛才的分析是否準確:
SQL>
CREATE OR REPLACE TRIGGER T_STATEMENT
2
BEFORE UPDATE ON T
3
BEGIN
4
DBMS_OUTPUT.PUT_LINE('STATEMENT');
5 END;
6
/
觸發器已建立
SQL>
CREATE OR REPLACE TRIGGER T_ROW
2
BEFORE UPDATE ON T
3
FOR EACH ROW
4
BEGIN
5
DBMS_OUTPUT.PUT_LINE('ROW:' || :OLD.ID);
6
END;
7
/
觸發器已建立
SQL> SET SERVEROUT ON
SQL>
DECLARE
2
TYPE T_ID IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
3
V_ID T_ID;
4
BEGIN
5
SELECT ID
6
BULK COLLECT INTO V_ID
7
FROM T;
8
FORALL I IN V_ID.FIRST..V_ID.LAST
9
UPDATE T
10
SET ID = V_ID(I)
11
WHERE ID = V_ID(I);
12
END;
13
/
STATEMENT
ROW:1
STATEMENT
ROW:2
STATEMENT
ROW:3
STATEMENT
ROW:4
STATEMENT
ROW:5
STATEMENT
ROW:6
PL/SQL 過程已成功完成。
SQL>
DECLARE
2
TYPE T_ID IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
3
V_ID T_ID;
4
BEGIN
5
SELECT ID
6
BULK COLLECT INTO V_ID
7
FROM T;
8
FORALL I IN V_ID.FIRST..V_ID.LAST
9
UPDATE T
10
SET ID = V_ID(I);
11
END;
12
/
STATEMENT
ROW:1
ROW:2
ROW:3
ROW:4
ROW:5
ROW:6
STATEMENT
ROW:1
ROW:1
ROW:1
ROW:1
ROW:1
ROW:1
STATEMENT
ROW:2
ROW:2
ROW:2
ROW:2
ROW:2
ROW:2
STATEMENT
ROW:3
ROW:3
ROW:3
ROW:3
ROW:3
ROW:3
STATEMENT
ROW:4
ROW:4
ROW:4
ROW:4
ROW:4
ROW:4
STATEMENT
ROW:5
ROW:5
ROW:5
ROW:5
ROW:5
ROW:5
PL/SQL 過程已成功完成。
對於FORALL中的UPDATE語句,執行的次數由FORALL語句中陣列的長度決定,這與INSERT語句只執行一次是有明顯不同的。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4227/viewspace-697251/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- FORALL執行UPDATE語句(二)
- FORALL執行DELETE語句delete
- 一條update SQL語句是如何執行的SQL
- 執行update語句,用沒用到索引,區別大嗎?索引
- 深入解讀MySQL InnoDB儲存引擎Update語句執行過程MySql儲存引擎
- mySQL 執行語句執行順序MySql
- 【SQL】10 SQL UPDATE 語句SQL
- Sql Server系列:Update語句SQLServer
- SQL update select語句SQL
- for語句執行順序
- sql語句批量執行SQL
- MySQL中UPDATE語句裡SET後使用AND的執行過程和結果分析MySql
- 查詢正在執行的sql語句及該語句執行的時間SQL
- MySQL -update語句流程總結MySql
- ORACLE多表關聯UPDATE語句Oracle
- MySQL的update語句避坑MySql
- ORACLE多表關聯UPDATE 語句Oracle
- MySql與Sql Server Update語句MySqlServer
- update語句的優化方式優化
- MySQL語句執行分析(一)MySql
- MySQL語句執行分析(二)MySql
- sql語句如何執行的SQL
- SQL語句執行順序SQL
- PHP執行批量mysql語句PHPMySql
- 執行大的sql語句SQL
- toad執行sql語句SQL
- ORACLE UPDATE 語句語法與效能分析Oracle
- 每一千行UPDATE語句後插入一條COMMIT語句的編輯方法MIT
- 查詢Oracle正在執行的sql語句及執行該語句的使用者OracleSQL
- YCSB擴充套件-語句執行頻率,執行指定的測試查詢語句套件
- mysql執行sql語句過程MySql
- Mybatis 動態執行SQL語句MyBatisSQL
- mysql的sql語句執行流程MySql
- sql語句執行緩慢分析SQL
- SQL 語句的執行順序SQL
- Select語句執行順序
- 後臺執行SQL語句(oracle)SQLOracle
- takes_ownership(s)語句執行