web-dev-qa-db-ja.com

プロシージャOracle内の一時テーブル

私は今状況にいます。 Mysql 5.0からOracle 11gにいくつかの手順を移行しています。 Mysqlプロシージャにより、次のことが可能になります。
1。一時テーブルを作成します
2。一時テーブルにデータを挿入する/これらのテーブルをクエリする/プロセスを実行する
一時テーブルを削除します

検索してみたところ、EXECUTE IMMEDIATEステートメントがないと、プロシージャ内でDDLステートメントを作成できないことがわかりました。そのステートメントで一時テーブルを作成しようとしましたが、すぐにいくつかの値を挿入しましたが、テーブルがまだ存在していないため機能しません。一時テーブルを作成する関数を作成し、それをプロシージャから呼び出してみましたが、同じことが起こりました。

MySQLで行っているのと同じ手順を実行する必要があります。この状況は非常に頻繁に発生し(この種の「問題」には非常に多くの手順があります)、それらは非常に大きいです。

どのようなオプションがありますか、何をお勧めしますか?

6

MySQLで一時テーブルを作成する理由によって異なります。

多くの場合、他のデータベースに一時テーブルを作成する人々は、リーダーがライターをブロックせず、ライターがリーダーをブロックしないというOracleに存在しない制限を回避するためにそうしています。他のデータベースでは、通常、プロセスが同じデータを必要とする他のプロセスをブロックしないように、永続テーブルから一時テーブルにデータをコピーします。ただし、Oracleはマルチバージョンの読み取り一貫性を提供するため、これはOracleでは必要ありません(または有益ではありません)。プロセスは、他の誰かをブロックすることを心配することなく、実際のテーブルにあるデータを処理できます。それが現在の状況である場合、適切な応答は、一時テーブルを削除して永続テーブルからデータを処理することです。

データの一時コピーが本当に必要であると想定して、グローバル一時テーブルを作成できます。これらのテーブルは、永続テーブルのようにコードの外で作成し、コード内の永続テーブルのように使用します。グローバル一時テーブルにより、各セッションは、セッションが挿入したデータのみを確認できます。唯一の違いは、プロシージャ内でテーブルの構造を削除して再作成しないことです。

もう1つの方法は、一時テーブルを使用するのではなく、操作するPL/SQLコレクションにデータを取り込むことです。 PL/SQLコレクションはサーバーのPGA(Oracleのメモリ構造の1つ)に格納されるため、通常、特に処理するデータが大量にある場合や、同時にデータを処理する多くのセッションがある場合は、コレクションのサイズを制限する必要があります。あなたは次のようなことができます

DECLARE
  TYPE emp_tbl IS TABLE OF emp%rowtype;
  l_emps emp_tbl;

  CURSOR emp_cur 
      IS SELECT *
           FROM emp;
BEGIN
  OPEN emp_cur;
  LOOP
    -- Fetch 10 rows at a time from the cursor into the collection.
    -- You'd realistically want a larger limit, something between 100 and 1000 generally
    FETCH emp_cur 
     BULK COLLECT INTO l_emps
    LIMIT 10;

    EXIT WHEN l_emps.COUNT = 0;

    -- An example of manipulating the collection in memory
    FOR i IN 1 .. l_emps.COUNT
    LOOP
      l_emps(i).sal := l_emps(i).sal * 2;
    END LOOP;

    -- And an example of using the collection to update a table
    FORALL i IN 1 .. l_emps.COUNT
      UPDATE emp
         SET sal = l_emps(i).sal
       WHERE empno = l_emps(i).empno;
  END LOOP;
END;

もちろん、上記の例では、単にすべての従業員の給与を2倍にするUPDATEステートメントを発行する方がはるかに簡単(かつ効率的)です。

8
Justin Cave