3

数据库:甲骨文 11g

有没有办法执行以下操作:

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

我知道如何遍历光标,但我正在寻找更精简的东西。

PL/SQL 很好,但没有循环。
使用 SQL 提示也很好。

如果这只是甲骨文无法处理的事情,那么悲伤就会接踵而至(大多数情况下我只是好奇,因为我已经有另一种方法在起作用)。

注意:该应用程序有数千亿条记录。每天创造数百万。INSERT INTO SELECT 不适用于如此大的数据集。特别是当有同样大的集合并行运行时。

4

3 回答 3

8

Oracle 不允许语句具有临时提交,不。这样做会违反 ACID 数据库的基本属性。如果语句在 N 行失败,会发生什么?Oracle 将无法回滚以前提交的行。它不知道哪些行已处理,哪些行未处理。因此,您的声明将部分成功,并且您的数据库将处于未知状态。使用关系数据库的主要好处之一是完全避免这种结果。

你为什么要首先做一个临时提交?这将使您的代码变慢并导致您使用更多资源。这将迫使您编写一堆代码以使您的流程可重新启动(即,您必须跟踪哪些行已被处理,哪些未处理,以便您可以回滚部分完成的更改或在失败时重新启动流程在中间)。它会让你的代码更难测试。几乎没有充分的理由进行临时提交。

于 2012-04-16T15:13:51.340 回答
5

Oracle 不提供这样的 SQL 结构。使用带有游标的 PL/SQL 和 FORALL 语句可以为您完成...但是:

幸好甲骨文没有提供这样的悲伤。Oracle 是建立在 ACID 原则之上的 RDBMS。I 代表隔离,在 Oracle 中默认为 READ COMMITTED。这意味着其他并发事务无法在中途看到您的事务。它可以防止其他会话看到不一致的数据。使用 RDBMS 的基石之一。

这给我们带来了这里最重要的问题:为什么你会想要这样的构造?

我希望不要害怕“大”交易。

于 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 回答