3

DB: オラクル 11g

次のようなことをする方法はありますか?

INSERT INTO T1
    (V1, V2)
COMMIT EVERY X
AS
SELECT (V1, V2) FROM T2;

カーソルをループする方法は知っていますが、もっと合理化されたものを探しています。

PL/SQL は問題ありませんが、ループはありません。
SQL ヒントを使用することも有効です。

これがオラクルが処理できないものである場合、悲しみが続きます(別のアプローチがすでに機能しているため、ほとんどの場合、私はただ興味があります)。

注: アプリケーションには数千億のレコードがあります。1 日に数百万が作成されます。INSERT INTO SELECT は、このような大規模なデータ セットでは機能しません。特に、同じように大きなセットが並行して実行されている場合。

4

3 に答える 3

8

Oracle では、ステートメントに暫定的なコミットを許可していません。これを行うと、ACID データベースの基本的な特性に違反します。ステートメントが行 N で失敗した場合はどうなりますか? Oracle は、以前にコミットされた行をロールバックできません。どの行が処理され、どの行が処理されていないかはわかりません。したがって、ステートメントは部分的に成功し、データベースは不明な状態のままになります。リレーショナル データベースを使用する主な利点の 1 つは、まさにそのような結果を回避できることです。

そもそもなぜ暫定コミットをしたいのですか?これにより、コードが遅くなり、より多くのリソースを使用することになります。プロセスを再起動可能にするために大量のコードを書く必要があります (つまり、部分的に完了した変更をロールバックするか、失敗した場合にプロセスを再起動できるように、どの行が処理され、どの行が処理されていないかを追跡する必要があります)。途中で)。また、コードのテストが非常に難しくなります。暫定コミットを行う正当な理由はほとんどありません。

于 2012-04-16T15:13:51.340 に答える
5

Oracle は、そのような SQL 構造を提供していません。PL/SQL をカーソルと FORALL ステートメントで使用すると、それを行うことができます... しかし:

オラクルがそのような悲しみを提供しないのは良いことです。Oracle は、ACID の原則に基づいて構築された RDBMS です。I は分離を表し、Oracle ではデフォルトで READ COMMITTED になります。つまり、他の同時トランザクションはあなたのトランザクションを途中で見ることができません。他のセッションが一貫性のないデータを参照するのを防ぎます。RDBMS を使用する上での基礎の 1 つです。

ここで最も重要な質問に至ります。なぜそのような構造が必要なのですか?

「大きな」取引への恐怖ではないことを願っています。

于 2012-04-16T15:19:06.090 に答える
0

私はそれをチェックしませんでしたが、おそらくbulk insertsこれを達成することができます:

DECLARE
  TYPE ARRAY IS TABLE OF T2%ROWTYPE;
  l_data ARRAY;
  x NUMBER;

  CURSOR c IS SELECT V1, V2 FROM T2;

BEGIN
    OPEN c;
    LOOP
    FETCH c BULK COLLECT INTO l_data LIMIT x;

    FORALL i IN 1..l_data.COUNT
    INSERT INTO T1 VALUES l_data(i);

    COMMIT;

    EXIT WHEN c%NOTFOUND;
    END LOOP;
    CLOSE c;
END;

しかし、ジャスティン・ケイブとして、なぜ???

于 2012-04-16T15:19:49.660 に答える