INSERT 不适用于 PL/SQL 块中的 GLOBAL TEMPORARY TABLE

Chr*_*ven 2 oracle toad global temporary

我是 Oracle 脚本新手,在将数据插入全局临时表时遇到问题。这是我在 Toad 中创建的脚本:

    SET SERVEROUTPUT ON;

    DECLARE
        tempTwwIDExist NUMBER;
        v_sql LONG; 
    BEGIN
        SELECT COUNT(*) INTO tempTwwIDExist FROM USER_TABLES WHERE table_name = UPPER('tempTwwID');
        DBMS_OUTPUT.PUT_LINE(tempTwwIDExist);

        IF (tempTwwIDExist > 0) THEN 
        BEGIN
                EXECUTE IMMEDIATE 'TRUNCATE TABLE tempTwwID';
                EXECUTE IMMEDIATE 'DROP TABLE tempTwwID';
        END;
        END IF;

        EXECUTE IMMEDIATE 'CREATE GLOBAL TEMPORARY TABLE tempTwwID (id NUMBER NOT NULL, SITEID NUMBER) ON COMMIT DELETE ROWS';

        EXECUTE IMMEDIATE 'INSERT INTO tempTwwID (id, SITEID) VALUES (1,123)';

    END;
    /
Run Code Online (Sandbox Code Playgroud)

但是,当我运行 SELECT 语句以从 tempTwwID 获取所有数据时,尽管此脚本使用 EXECUTE IMMEDIATE 运行 INSERT 语句(END; 之前的最后一行代码),但现在仍返回行。

我希望你能帮我解决这个问题。提前致谢。

Ale*_*ole 5

您已使用 定义了全局临时表ON COMMIT DELETE ROWS。如果您在匿名块内显式提交(无论是否通过execute immediate,这是毫无意义的)或在该块之后显式提交,则该会话中的后续查询将不再看到插入的数据。

可能不太明显的是Toad 可以配置为自动提交。如果设置了该值,则块中的更改将在运行后立即自动提交,这意味着在块中插入的行将在您查询之前被删除。如果将 GTT 更改为,ON COMMIT PRESERVE ROWS您将在查询时看到数据。

这不仅限于蟾蜍。您可以在 SQL Developer 或 SQL*Plus 中看到同样的事情set autocommit on。如果您没有充分的理由自动提交,那么您可以将其关闭。


正如 Jeffrey Kemp 所说,您不应该在运行时创建 GTT(或进行任何模式修改);模式应该是受控的和静态的。Oracle 的 GTT 与您在其他数据库中动态定义的本地临时表不同,并且应该创建一次。临时数据是数据,而不是表对象

在运行时定义事物会进行您可能不期望的隐式提交(因为DDL 提交),成本高昂,存在会话之间发生冲突的风险,并迫使您在不需要的地方使用动态 SQL;这反过来又阻止了在编译时检查代码,这意味着直到运行时才会看到语法错误。