INSERT 在 PL/SQL 块中对 GLOBAL TEMPORARY TABLE 不起作用

INSERT not working on GLOBAL TEMPORARY TABLE in a PL/SQL block

我是 Oracle 脚本的新手,在将数据插入全局临时文件时遇到问题 table。这是我在 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;
    /

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

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

您已经用 ON COMMIT DELETE ROWS 定义了全局临时 table。如果您在匿名块内明确提交 - 无论是否通过 execute immediate,这是没有意义的 - 或者在该块之后,该会话中的后续查询将不再看到插入的数据。

可能不太明显的是 Toad can be configured to auto-commit。如果已设置,那么块中的更改将在 运行 时自动提交,这意味着插入块中的行将在您可以查询之前被删除。如果您将 GTT 更改为 ON COMMIT PRESERVE ROWS,您将在查询时看到数据。

这不仅限于 Toad;您可以在 SQL Developer 或 SQL*Plus 和 set autocommit on 中看到相同的内容。如果您没有充分的理由自动提交,那么您可以将其关闭。


正如 Jeffrey Kemp 所说,您不应该在 运行 时间创建 GTT(或任何模式修改);模式应该是受控的和静态的。 Oracle 的 GTT 与您在其他数据库中即时定义的本地临时 table 不同,应该创建一次。 It is the data that is temporary, not the table object.

在 运行 时间定义事物会隐式提交您可能没有预料到的(因为 DDL commits),代价高昂,会话之间存在冲突风险,并迫使您使用动态 SQL在不需要的地方;这反过来又阻止了在编译时检查代码,这意味着直到 运行time.

才会看到语法错误

就我而言,这篇文章对我有用:https://community.oracle.com/tech/developers/discussion/632411/temporary-tables-insert

我使用 Toad for Oracle,例如,有 2 个 sql,一个插入和一个来自临时 table 的 select,称为 TempTable:

Insert into TempTable select '123' from dual;
Select * from TempTable ;

如果我使用键盘 F5 单独执行这两个 sql,第一个插入显示创建的一行,第二个 select 不显示任何行。

但是如果我将这2个sql放在一起并突出显示它们,使用F5一次连续执行它们,将成功显示TempTable中的select 1行。

我想当突出显示多个 sql 一起执行时,Toad 会将它们视为在同一会话中。