私は今状況にいます。 Mysql 5.0からOracle 11gにいくつかの手順を移行しています。 Mysqlプロシージャにより、次のことが可能になります。
1。一時テーブルを作成します
2。一時テーブルにデータを挿入する/これらのテーブルをクエリする/プロセスを実行する
。一時テーブルを削除します
検索してみたところ、EXECUTE IMMEDIATEステートメントがないと、プロシージャ内でDDLステートメントを作成できないことがわかりました。そのステートメントで一時テーブルを作成しようとしましたが、すぐにいくつかの値を挿入しましたが、テーブルがまだ存在していないため機能しません。一時テーブルを作成する関数を作成し、それをプロシージャから呼び出してみましたが、同じことが起こりました。
MySQLで行っているのと同じ手順を実行する必要があります。この状況は非常に頻繁に発生し(この種の「問題」には非常に多くの手順があります)、それらは非常に大きいです。
どのようなオプションがありますか、何をお勧めしますか?
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
ステートメントを発行する方がはるかに簡単(かつ効率的)です。