【Oracle】グローバル一時テーブル(GTT)の作成と使い方完全解説|トランザクション限定・セッション限定・確認方法まで

OracleのグローバルテンポラリテーブルはData Pump Export(CREATE GLOBAL TEMPORARY TABLE)で作成する一時テーブルです。テーブル定義は永続的に保存されますが、格納したデータはトランザクションまたはセッションの終了時に自動削除されます。

本記事では2種類の一時テーブル(トランザクション限定・セッション限定)の違い、作成・操作・確認方法から実運用のユースケースまでを完全解説します。

スポンサーリンク

グローバル一時テーブル(GTT)とは

項目 通常テーブル グローバル一時テーブル(GTT)
テーブル定義 永続 永続(DDLは残る)
データの有効期間 明示的に削除するまで トランザクション終了 or セッション終了まで
マルチユーザー 全ユーザーで共有 セッションごとにデータが完全に独立
REDOログ 生成される 最小限(パフォーマンス向上)
ロック競合 発生しうる セッション間でロック競合なし

2種類のGTT:ON COMMIT の違い

オプション データ削除のタイミング 主な用途
ON COMMIT DELETE ROWS COMMIT または ROLLBACK 時 1トランザクション内の作業領域
ON COMMIT PRESERVE ROWS セッション切断時 複数トランザクションにまたがる作業領域
デフォルト: ON COMMIT DELETE ROWS がデフォルトです。省略した場合はトランザクション終了時にデータが削除されます。

GTTの作成構文

トランザクション限定(COMMITでデータ削除)

SQL — ON COMMIT DELETE ROWS(デフォルト)
CREATE GLOBAL TEMPORARY TABLE work_orders (
  order_id   NUMBER,
  product_cd VARCHAR2(20),
  qty        NUMBER,
  created_at DATE DEFAULT SYSDATE
) ON COMMIT DELETE ROWS;

-- COMMITまたはROLLBACKするとデータが自動削除される

セッション限定(セッション終了でデータ削除)

SQL — ON COMMIT PRESERVE ROWS
CREATE GLOBAL TEMPORARY TABLE session_cart (
  cart_id    NUMBER,
  item_cd    VARCHAR2(20),
  qty        NUMBER,
  unit_price NUMBER(12, 2)
) ON COMMIT PRESERVE ROWS;

-- COMMITしてもデータは残り、セッション切断時に削除される

GTTへのDML操作

GTTは通常のテーブルと同様に INSERT・SELECT・UPDATE・DELETE が使えます。ただし TRUNCATE は使用できません(DELETE で代替)。

SQL — GTTへのDML操作例
-- データ挿入
INSERT INTO session_cart (cart_id, item_cd, qty, unit_price)
VALUES (1, 'ITEM001', 3, 1500);

-- 他テーブルからの一括挿入
INSERT INTO work_orders (order_id, product_cd, qty)
SELECT order_id, product_cd, qty
  FROM orders
 WHERE status = 'PENDING';

-- 参照
SELECT item_cd, qty, unit_price, qty * unit_price AS subtotal
  FROM session_cart
 ORDER BY item_cd;

-- 更新・削除
UPDATE session_cart SET qty = 5 WHERE item_cd = 'ITEM001';
DELETE FROM session_cart WHERE qty = 0;

-- 全件削除(TRUNCATEは不可のためDELETE ALL)
DELETE FROM session_cart;

GTTにインデックスを作成する

GTTにもインデックスを作成できます。インデックスのデータもセッション・トランザクション限定です。

SQL — GTTへのインデックス作成
CREATE INDEX idx_work_orders_product
  ON work_orders (product_cd);

-- 複合インデックスも作成可能
CREATE INDEX idx_session_cart_item
  ON session_cart (item_cd, cart_id);

GTTの存在を確認する

SQL — USER_TABLES / ALL_TABLES でGTTを確認
-- 自スキーマのGTTを一覧表示
SELECT table_name,
       duration   -- SYS$TRANSACTION または SYS$SESSION
  FROM user_tables
 WHERE temporary = 'Y'
 ORDER BY table_name;

-- DURATION列の値
--   SYS$TRANSACTION = ON COMMIT DELETE ROWS
--   SYS$SESSION     = ON COMMIT PRESERVE ROWS
SQL — 現在のセッションでGTTにデータが入っているか確認
SELECT COUNT(*) FROM session_cart;

-- セッションをまたいで確認するには別セッションでも同じSQL
-- ただし別セッションのデータは見えない(独立している)

GTTの削除(DROP)

SQL — GTTのDROP
-- GTTのDROPは他のセッションがGTTを使用していない場合のみ可能
DROP TABLE session_cart;

-- 他セッションで使用中の場合はエラー: ORA-14452
注意: GTTのDROPは他のセッションがそのGTTにアクセスしていない状態でのみ実行できます。アクセス中のセッションがある場合は ORA-14452: attempt to create, alter or drop an index on temporary table already in use エラーが発生します。

Oracle 18c以降:プライベート一時テーブル(PTT)

Oracle 18c以降では、CREATE PRIVATE TEMPORARY TABLE で作成するプライベート一時テーブル(PTT)も利用できます。GTTとの主な違いは以下の通りです。

比較項目 GTT(グローバル) PTT(プライベート)
テーブル定義の寿命 永続(DDLが残る) セッションまたはトランザクション終了で定義も消える
他セッションからの可視性 定義は見える(データは見えない) 定義もデータも見えない
名前のプレフィックス 任意 ORA$PTT_ が必須
対応バージョン 全バージョン Oracle 18c以降
SQL — プライベート一時テーブルの作成(Oracle 18c以降)
CREATE PRIVATE TEMPORARY TABLE ORA$PTT_work (
  id   NUMBER,
  memo VARCHAR2(100)
) ON COMMIT DROP DEFINITION; -- COMMIT時に定義ごと削除

まとめ

用途 選択するオプション
1トランザクション内の作業用バッファ ON COMMIT DELETE ROWS(デフォルト)
セッション中ずっとデータを保持したい ON COMMIT PRESERVE ROWS
使い捨て(定義も不要) PTT(Oracle 18c以降)
GTTの種類を確認 USER_TABLES の DURATION 列で判断
❓ よくある質問(FAQ)  ▲ クリックで開閉

Q. GTTにCOMMITしても他のセッションからデータが見えないのはなぜか?
A. GTTのデータはセッション固有のセグメントに格納されるため、物理的に他セッションからは参照できない仕組みになっています。テーブル定義は共有されますが、データ領域は完全に独立しています。

Q. TRUNCATE TABLE をGTTで実行できないのはなぜか?
A. TRUNCATE はDDL文であるため、GTTのデータ削除には使えません。代わりに DELETE FROM テーブル名 を使用するか、ON COMMIT DELETE ROWS の場合はCOMMITするとデータが自動削除されます。

Q. GTTと通常テーブルのどちらが速いか?
A. 一般的にGTTのほうが高速です。GTTへのDMLはREDOログの生成量が最小限に抑えられ、UNDOも削減されます。大量データの一時的な集計・変換処理ではGTTを使うことでパフォーマンスが大幅に向上するケースがあります。