🌍

グローバル一時表とプライベート一時表の違い

に公開

はじめに

Oracle Master Silver SQL の学習中に、「一時表のデータはいつ消えるのか?」という点が気になったため、
グローバル一時表とプライベート一時表の違いを実際に SQL 実験で確認しました。

特に、ON COMMIT DELETE ROWS や ON COMMIT PRESERVE DEFINITION などの指定によって
データ削除のタイミングがどう変化するかを検証しています。

一時表とは

一時表とはデータを一時的に保管するための表です。一時表にINSERTしたデータはそのセッションからのみ参照可能で、使用終了したら自動的に削除されます。
一時表にはグローバル一時表とプライベート一時表が存在します。

グローバル一時表

(GLOBAL TEMPORARY TABLE)は「テーブルの定義だけが共有され、データは各セッションごとに独立して存在する」という特殊な構造を持ちます。

bash-4.2$ sqlplus user_a/a@localhost/XEPDB1

SQL*Plus: Release 21.0.0.0.0 - Production on Fri Oct 17 17:56:32 2025
Version 21.3.0.0.0

Copyright (c) 1982, 2021, Oracle.  All rights reserved.


Connected to:
Oracle Database 21c Express Edition Release 21.0.0.0.0 - Production
Version 21.3.0.0.0

SQL> CREATE GLOBAL TEMPORARY TABLE temp_orders (
  orde  2  r_id NUMBER,
  amount   NUMBER
) ON COMMIT DELETE ROWS;

INSERT INTO temp_orders VALUES (1, 1000);
SELECT * FROM temp_orders;

Table created.

SQL> SQL>
1 row created.

SQL>
  ORDER_ID     AMOUNT
---------- ----------
         1       1000

SQL> exit
Disconnected from Oracle Database 21c Express Edition Release 21.0.0.0.0 - Production
Version 21.3.0.0.0
bash-4.2$ sqlplus sys/Password123@localhost/XEPDB1 as sysdba

SQL*Plus: Release 21.0.0.0.0 - Production on Fri Oct 17 17:57:09 2025
Version 21.3.0.0.0

Copyright (c) 1982, 2021, Oracle.  All rights reserved.


Connected to:
Oracle Database 21c Express Edition Release 21.0.0.0.0 - Production
Version 21.3.0.0.0

SQL> GRANT SELECT ON user_a.temp_orders TO user_b;

Grant succeeded.

SQL> exit
Disconnected from Oracle Database 21c Express Edition Release 21.0.0.0.0 - Production
Version 21.3.0.0.0
bash-4.2$ sqlplus user_b/b@localhost/XEPDB1

SQL*Plus: Release 21.0.0.0.0 - Production on Fri Oct 17 17:57:32 2025
Version 21.3.0.0.0

Copyright (c) 1982, 2021, Oracle.  All rights reserved.


Connected to:
Oracle Database 21c Express Edition Release 21.0.0.0.0 - Production
Version 21.3.0.0.0

SQL> SELECT * FROM user_a.temp_orders;

no rows selected

ユーザーBがデータを見られなかったのは、データがセッションごとに独立しているためであり、ユーザーAのコミット前であればユーザーAのセッションからは見えますが、コミット後はユーザーAのセッションからも見えなくなります。

パターン①:DELETE ROWS(または省略時のデフォルト)

-- グローバル一時表の作成
CREATE GLOBAL TEMPORARY TABLE temp_orders (
  order_id NUMBER,
  amount   NUMBER
) ON COMMIT DELETE ROWS;

-- データ登録と確認
INSERT INTO temp_orders VALUES (1, 1000);
SELECT * FROM temp_orders;

ORDER_ID | AMOUNT
---------- ----------
1         | 1000

-- コミット後に確認
COMMIT;
SELECT * FROM temp_orders;

no rows selected

パターン②:PRESERVE ROWS

SQL> CREATE GLOBAL TEMPORARY TABLE temp_orders (
  orde  2  r_id NUMBER,
  amount NUMBER
) ON COMMIT PRESERVE ROWS;

Table created.

SQL> INSERT INTO temp_orders VALUES (1, 1000);

1 row created.

SQL> INSERT INTO temp_orders VALUES (2, 2000);

1 row created.

SQL> SELECT * FROM temp_orders;

  ORDER_ID     AMOUNT
---------- ----------
         1       1000
         2       2000

SQL> COMMIT;

Commit complete.

SQL> SELECT * FROM temp_orders;

  ORDER_ID     AMOUNT
---------- ----------
         1       1000
         2       2000

プライベート一時表

グローバル一時表(GTT)とは異なり、

✅ テーブル定義もデータもセッションごとに完全に独立し、他ユーザーからは一切見えない

という、より“個人専用・短命”な一時表です。

bash-4.2$ sqlplus user_a/a@localhost/XEPDB1

SQL*Plus: Release 21.0.0.0.0 - Production on Fri Oct 17 18:43:39 2025
Version 21.3.0.0.0

Copyright (c) 1982, 2021, Oracle.  All rights reserved.

Last Successful login time: Fri Oct 17 2025 18:19:30 +00:00

Connected to:
Oracle Database 21c Express Edition Release 21.0.0.0.0 - Production
Version 21.3.0.0.0

SQL> CREATE PRIVATE TEMPORARY TABLE ora$ptt_temp_orders (
  order_id NUMBER,
  amount   NUMBER
) ON COMMI  2    3    4  T PRESERVE DEFINITION;

Table created.

SQL> INSERT INTO ora$ptt_temp_orders VALUES (1, 1000);
SELECT * FROM ora$ptt_temp_orders;

1 row created.

SQL>
  ORDER_ID     AMOUNT
---------- ----------
         1       1000

SQL> COMMIT;
SELECT * FROM ora$ptt_temp_orders;

Commit complete.

SQL>
  ORDER_ID     AMOUNT
---------- ----------
         1       1000

SQL> exit
sqlplus user_a/a@localhost/XEPDB1
Disconnected from Oracle Database 21c Express Edition Release 21.0.0.0.0 - Production
Version 21.3.0.0.0
bash-4.2$ sqlplus user_a/a@localhost/XEPDB1

SQL*Plus: Release 21.0.0.0.0 - Production on Fri Oct 17 18:44:27 2025
Version 21.3.0.0.0

Copyright (c) 1982, 2021, Oracle.  All rights reserved.

Last Successful login time: Fri Oct 17 2025 18:43:40 +00:00

Connected to:
Oracle Database 21c Express Edition Release 21.0.0.0.0 - Production
Version 21.3.0.0.0

SQL> SELECT * FROM ora$ptt_temp_orders;
SELECT * FROM ora$ptt_temp_orders
              *
ERROR at line 1:
ORA-00942: table or view does not exist

ここでは、ON COMMIT 句の指定によって、データや定義がどのタイミングで削除されるかを確認してみます。

パターン①:ON COMMIT DROP DEFINITION

SQL> CREATE PRIVATE TEMPORARY TABLE ora$ptt_temp_orders (
  order_id NUMBER,
  amount   NUMBER
) ON COMMI  2    3    4  T DROP DEFINITION;

INSERT INTO ora$ptt_temp_orders VALUES (1, 1000);
SELECT * FROM ora$ptt_temp_orders;

Table created.

SQL> SQL>
1 row created.

SQL>
  ORDER_ID     AMOUNT
---------- ----------
         1       1000

SQL> COMMIT;
SELECT * FROM ora$ptt_temp_orders;

Commit complete.

SQL> SELECT * FROM ora$ptt_temp_orders
              *
ERROR at line 1:
ORA-00942: table or view does not exist

パターン➁:ON COMMIT PRESERVE DEFINITION


SQL> CREATE PRIVATE TEMPORARY TABLE ora$ptt_temp_orders (
  order_id NUMBER,
  amount   NUMBER
) ON COMMI  2    3    4  T PRESERVE DEFINITION;

INSERT INTO ora$ptt_temp_orders VALUES (1, 1000);
SELECT * FROM ora$ptt_temp_orders;

Table created.

SQL> SQL>
1 row created.

SQL>
  ORDER_ID     AMOUNT
---------- ----------
         1       1000

SQL> COMMIT;
SELECT * FROM ora$ptt_temp_orders;

Commit complete.

SQL>
  ORDER_ID     AMOUNT
---------- ----------
         1       1000

SQL>

まとめ

種類 定義の寿命 データの寿命 可視範囲 主な利用用途
グローバル一時表 永続(スキーマに残る) セッションまたはトランザクション単位 他ユーザーから定義参照可能(データ不可) アプリ共通の一時領域
プライベート一時表 一時(セッション終了で削除) セッション単位 作成したセッションのみ スクリプト内限定・一時処理用

Discussion