計算機三級考試數(shù)據(jù)庫存輔導(dǎo):不包含INTO的動態(tài)SQL不會增加序列值

字號:

在試圖增加序列的NEXTVAL的時候,無意中發(fā)現(xiàn)了這個問題。
    首先還是看看現(xiàn)象:
    SQL> CREATE SEQUENCE SEQ_TEST;
    序列已創(chuàng)建。
    SQL> SELECT SEQ_TEST.NEXTVAL FROM DUAL;
    NEXTVAL
    1 SQL> BEGIN
    2 FOR I IN 1..1000 LOOP
    3 EXECUTE IMMEDIATE 'SELECT SEQ_TEST.NEXTVAL FROM DUAL';
    4 END LOOP;
    5 END;
    6 /
    PL/SQL 過程已成功完成。
    SQL> SELECT SEQ_TEST.NEXTVAL FROM DUAL;
    NEXTVAL
    1 可以看到,序列SEQ_TEST的NEXTVAL并不像想象中的提高了1000,而給人的感覺似乎根本沒有執(zhí)行。
    避免的方法也簡單,只需要添加INTO語句:
    SQL> DECLARE
    2 TYPE T_ID IS TABLE OF NUMBER;
    3 V_ID T_ID;
    4 BEGIN
    5 FOR I IN 1..1000 LOOP
    6 EXECUTE IMMEDIATE 'SELECT SEQ_TEST.NEXTVAL FROM DUAL'
    7 BULK COLLECT INTO V_ID;
    8 END LOOP;
    9 END;
    10 /PL/SQL 過程已成功完成。SQL> SELECT SEQ_TEST.NEXTVAL FROM DUAL;
    NEXTVAL
    1003
    產(chǎn)生這種情況有兩種可能,一是由于Oracle發(fā)現(xiàn)動態(tài)SQL的執(zhí)行沒有INTO語句,不需要返回結(jié)果,因此根本沒有執(zhí)行;二是Oracle只是打開游標,并沒有FETCH數(shù)據(jù),因此造成了序列的值沒有發(fā)生變化。
    最后通過一個測試檢驗一下,到底是哪種情況造成了上面的現(xiàn)象:
    SQL> CREATE OR REPLACE FUNCTION F_TEST RETURN NUMBER AS
    2 BEGIN
    3 DBMS_LOCK.SLEEP(10);
    4 RETURN 0;
    5 END;
    6 /函數(shù)已創(chuàng)建。
    SQL> SET TIMING ON
    SQL> BEGIN
    2 EXECUTE IMMEDIATE 'SELECT F_TEST FROM DUAL';
    3 END;
    4 / PL/SQL 過程已成功完成。
    已用時間: 00: 00: 00.10
    SQL> DECLARE
    2 V_ID NUMBER;
    3 BEGIN
    4 EXECUTE IMMEDIATE 'SELECT F_TEST FROM DUAL' INTO V_ID;
    5 END;
    6 / PL/SQL 過程已成功完成。
    已用時間: 00: 00: 10.29
    通過對比就可以發(fā)現(xiàn),如果缺少INTO語句,那么動態(tài)SQL就不會執(zhí)行。