我是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;
/
但是,当我运行SELECT语句从tempTwwID获取所有数据时,现在返回行,尽管INSERT语句此脚本使用EXECUTE IMMEDIATE运行(END之前的最后一行代码;)。
我希望你能帮助我。提前谢谢。
答案 0 :(得分:3)
您已使用ON COMMIT DELETE ROWS
定义了全局临时表。如果您在匿名块中明确提交 - 无论是否通过execute immediate
,这是毫无意义的 - 或者在块之后,那么该会话中的后续查询将不再能够看到插入的数据。
可能不太明显的是Toad can be configured to auto-commit。如果已设置,那么块中的更改将在运行后立即自动提交,这意味着将在您查询之前删除插入块中的行。如果您将GTT更改为ON COMMIT PRESERVE ROWS
,那么您在查询时会看到数据。
这并不仅限于Toad;您可以使用set autocommit on
在SQL Developer或SQL * Plus中看到相同的内容。如果您没有充分的理由自动提交,那么您可以将其关闭。
正如Jeffrey Kemp所说,你不应该在运行时创建你的GTT(或任何进行任何架构修改);架构应该受到控制并且是静态的。 Oracle的GTT与您在其他数据库中即时定义的本地临时表不同,应该创建一次。 It is the data that is temporary, not the table object
在运行时定义事物会导致您可能不期望的隐式提交(因为DDL commits),代价高昂,会话之间存在风险冲突,并迫使您在不应该使用的情况下使用动态SQL;这反过来会阻止在编译时检查代码,这意味着在运行时之前不会看到语法错误。
答案 1 :(得分:0)
就我而言,这篇文章对我有用:https://community.oracle.com/tech/developers/discussion/632411/temporary-tables-insert
我使用 Toad for Oracle,例如,有 2 个 sql,一个插入和一个从临时表中选择,称为 TempTable
:
Insert into TempTable select '123' from dual;
Select * from TempTable ;
如果我使用键盘 F5
单独执行这两个 sql,首先插入显示创建的一行,然后选择显示没有行。
但是如果我将这 2 个 sql 放在一起并突出显示它们,使用 F5
一次连续执行它们,将成功显示从 TempTable 中选择 1 行。
我想当突出显示多个 sql 一起执行时,Toad 会将它们视为在同一个会话中。