助け合いフォーラム
CREATE GLOBAL TEMPORARY TABLE temp
(
temp_id NUMBER(2),
temp_name VARCHAR2(20)
)
ON COMMIT PRESERVE ROWS;
INSERT INTO temp VALUES (1, 'tempA');
COMMIT;
この後の説明として正しい記述はどれですか(2つ選択して下さい)。
正解
TEMP表のデータは1件である
他のセッションからTEMP表を参照すると、データは0件である
解説
ON COMMIT PRESERVE ROWS句はセッション終了時にデータを削除(TRUNCATE)します。
TEMP表を作成した後はINSERT文で1件のデータを登録していますが、その後のCOMMIT文でトランザクションが終了した後もデータを参照できます。
以上より、
・TEMP表のデータは1件である
・他のセッションからTEMP表を参照すると、データは0件である
が正解です。
以下はSQL文の実行例です。
CREATE文を実行したセッション内ではTEMP表に挿入したデータを参照できます。他のセッションからはTEMP表の構造は確認できますがデータは参照できません。
(temp_id NUMBER(2),
temp_name VARCHAR2(20))
ON COMMIT PRESERVE ROWS;
INSERT INTO temp VALUES (1, 'tempA')
COMMIT;
SELECT * FROM temp;
その他の選択肢については以下のとおりです。
・TEMP表のデータは0件である
一時表作成時のON COMMIT PRESERVE ROWS句でセッション終了時にデータは削除されるので、トランザクション終了時(COMMIT時)は1件です。
・他のセッションからTEMP表は参照できない
グローバル一時表は全てのセッションから表の構造を参照できるので、誤りです。
・他のセッションからTEMP表を参照すると、データは1件である
一時表に挿入したデータはそのセッション内でのみ参照できるので、0件です。
参考
一時表は、トランザクションを終了またはセッションを切断するまでの間のみデータを保持する表です。一時表に挿入したデータはそのセッション内でのみ参照できます。セッション終了後も表の構造は残ります。
一時表のデータは永続表領域ではなく一時表領域に確保され、大量データを一時的に加工するなどの中間ワークテーブルとして利用できます。一時表へのDML文の実行時は通常の表のようにUNDO(変更前のデータ)を生成するので、処理をロールバックすることができます。
一時表にはセッション内だけ表の構造を参照できるプライベート一時表と、全てのセッションから表の構造を参照できるグローバル一時表があります。ここではグローバル一時表について記載します。
グローバル一時表にはCREATE INDEX文で1つ以上の索引を作成できますが、一時表のデータと同様に索引用のデータもトランザクションまたはセッションでのみ保持されます。索引の構造自体は表の構造と共に残ります。
また、グローバル一時表には通常の表のようにビューやシノニム、トリガーを作成できます。
グローバル一時表の作成方法は次のとおりです。
CREATE GLOBAL TEMPORARY TABLE 表名
(
列名 データ型
[,列名 データ型 …]
)
ON COMMIT [DELETE ROWS | PRESERVE ROWS];
・GLOBAL TEMPORARY
グローバル一時表を作成します。表の構造は全てのセッションから参照できます。
・ON COMMIT DELETE ROWS
トランザクション終了時にデータを削除(TRUNCATE)します。
(temp_id NUMBER(2),
temp_name VARCHAR2(20))
ON COMMIT DELETE ROWS;
INSERT INTO temp VALUES (1, 'tempA');
SELECT * FROM temp;
COMMIT;
SELECT * FROM temp;
・ON COMMIT PRESERVE ROWS
セッション終了時にデータを削除(TRUNCATE)します。
(temp_id NUMBER(2),
temp_name VARCHAR2(20))
ON COMMIT PRESERVE ROWS;
INSERT INTO temp VALUES (1, 'tempA');
COMMIT;
SELECT * FROM temp;
セッションの意味
次のSQL文を順番に実行しました。
CREATE GLOBAL TEMPORARY TABLE temp
(
temp_id NUMBER(2),
temp_name VARCHAR2(20)
)
ON COMMIT PRESERVE ROWS;
INSERT INTO temp VALUES (1, 'tempA');
COMMIT;
この後の説明として正しい記述はどれですか(2つ選択して下さい)。
・他のセッションからTEMP表を参照すると、データは0件である
・TEMP表のデータは1件である
「上記2点が正解の回答となります」
「他のセッションからTEMP表を参照すると、データは0件である」という内容について理解できないので教えてください。
ON COMMIT PRESERVE ROWSにてセッションが終了したら内容が削除される記述になっていると思っています。
セッションの定義←オラクルにユーザーがアクセスするとデータを行き来するために作成されるトンネルのようなものと解釈しています。
セッションというのは各ユーザーがオラクルにアクセスするたびにそれぞれのセッションが作成されるイメージを持っています。←あっているでしょうか?
もし、セッションが各ユーザがオラクルにアクセスするたびに作成されるのであれば、上記セッションは終了しておらず他のセッションからTEMP表を参照するとデータが1件表示されるのではないか?
この問題に対して私の知識不足でわからない部分がありますのでよろしければご教授お願いいたします。
セッションというのは各ユーザーがオラクルにアクセスするたびにそれぞれのセッションが作成されるイメージを持っています。←あっているでしょうか?
はい。その認識で良いと思います。
sqlplusなどを使用して対話的にアクセスしている状況ならば「各ユーザ」と呼べますし、開発した複数のアプリケーションからのアクセスであれば「各アプリケーション」とも呼べると思います。
もし、セッションが各ユーザがオラクルにアクセスするたびに作成されるのであれば、上記セッションは終了しておらず他のセッションからTEMP表を参照するとデータが1件表示されるのではないか?
ご認識の通り、セッションは終了していないと考えられます。終了しているのは「トランザクション」のみです。テーブル定義時に「ON COMMIT PRESERVE ROWS」を指定しているので、トランザクション終了後もデータを参照できています。(解説の実行例の通り)
この設問でのポイントは、「一時表のデータはあくまでもセッション内でのみ参照可能である」という点だと思います。他のセッションからは「表の構造」は参照できますが(解説の画像でいうところのDESC)、「データ」は参照できません(解説の画像でいうところのSELECT文の結果)。
一つのコマンドプロンプト(Linuxやmacであればターミナル等)を立ち上げて設問で提示されているSQLを実行後、同じコマンドプロンプト上から(同じセッション内からの意)はCOMMIT後も挿入したデータが参照できます。
もう一つ別のコマンドプロンプトを立ち上げて「temp」表に対してSELECT文を実行しても、データは参照できません。これは、前のコマンドプロンプトにおける最後の「COMMIT;」の前でも後でも同様です。
このことから「他のセッションからTEMP表を参照すると、データは0件である」が正答であると導き出せると思います。
コメント
この投稿に対して返信しませんか?