Oracle pl/sql forall:如何计算表空间已满(1654)错误的实际插入行数

Posted

技术标签:

【中文标题】Oracle pl/sql forall:如何计算表空间已满(1654)错误的实际插入行数【英文标题】:Oracle pl/sql forall: how to count actual number of inserted lines with tablespace full (1654) error 【发布时间】:2015-08-28 13:52:44 【问题描述】:

我有一个 PL/SQL 函数可以将许多行批量插入到表中。 我想知道正确插入了多少行,有多少行有问题(Oracle 11g 版)。

我做了类似的事情:

   (...)
   BEGIN
       FORALL i IN 1 .. num SAVE EXCEPTIONS
           insert into mytable values (myarr(i));
       EXCEPTION
       WHEN OTHERS THEN
           l_error_count := SQL%BULK_EXCEPTIONS.count;
           FOR i in 1 .. l_error_count LOOP
               dbms_output.put_line('Error #' || i || ',
                 iter: ' || SQL%BULK_EXCEPTIONS(i).ERROR_INDEX ||
                 ', code: ' || SQL%BULK_EXCEPTIONS(i).ERROR_CODE ||
                 ', ' || SQLERRM(-SQL%BULK_EXCEPTIONS(i).ERROR_CODE));
           END LOOP;
   END;

   FOR i IN 1 .. num LOOP
       DBMS_OUTPUT.PUT_LINE('Statement #' || i || ' inserted ' ||
         SQL%BULK_ROWCOUNT(i) || ' rows.');
   END LOOP;

   commit;
   (...)

通常它可以提供确切的数字或有错误的行(重复的 id 等),我可以每行列出一个。

当表空间用完空间时问题就来了(这是我无法控制的事情......):在这种情况下,即使 forall 插入了零行,它似乎也可以正常工作。 例如,如果我插入 10 行,我会得到:

错误 #1,迭代器:11,代码:1654,ORA-01654:无法在表空间 USERS_FULL 中将索引 TEST_SOL11_XS43018_USER_FULL.SYS_C00146274 扩展为 128 语句 #1 插入了 1 行。 语句#2 插入了 1 行。 语句#3 插入了 1 行。 语句#4 插入了 1 行。 语句#5 插入了 1 行。 语句#6 插入了 1 行。 语句 #7 插入了 1 行。 语句#8 插入了 1 行。 语句#9 插入了 1 行。 语句#10 插入了 1 行。

所以我得到一个 SINGLE 错误,它在迭代 #11 中声明(但我的循环是 1..10)。似乎前 10 次迭代有效,至少它接缝打印 SQL%BULK_ROWCOUNT(i)

如果没有真正写入 raw 的事实,因为表空间已满(我通过计算前后行来仔细检查 id)。

如果有办法我可以检查真正在表格中插入了多少行?

【问题讨论】:

您实际上有一个名为num 的变量,其值为10;你没有使用myarr.countSQL%BULK_ROWCOUNT.count 这只是一个sn-p来显示问题。我使用 num 是因为写和读更短。 是的,但是您建议您的循环是 1..10,; num 看起来像两个循环。 似乎很明显 myarr 有 > 10 个条目,并且成功插入了 10 个。插入的前 10 行的 TS 未满。也许;不确定在这种情况下它会做什么。没有其他活动 - 您真的确定没有真正插入 10 行吗? 我 100% 确定没有插入任何行。 我 100% 确定没有插入任何行。我在很多方面仔细检查了它。例如,我在 PL/SQL 块之前和之后做了 count(*),它给了我相同的值。我确定的另一个原因是因为我试图以这种方式插入单行:insert into mytable values (1);甲骨文给了我 ORA-01654 错误。如果不能插入单行,同样的方法是不能“批量”插入多行。 【参考方案1】:

引发了异常,因此事务被回滚。因此,没有插入任何行。

【讨论】:

我是批量插入,因此,例如,如果您尝试插入 1000 行,您会得到 5 个异常,这意味着插入了 995 行而没有插入 5 个。 “SAVE EXCEPTIONS”告诉 Oracle 将所有异常保存在一个数组中。这意味着异常不会导致自动回滚。

以上是关于Oracle pl/sql forall:如何计算表空间已满(1654)错误的实际插入行数的主要内容,如果未能解决你的问题,请参考以下文章

oracle pl/sql FORALL 语句

在 PL/SQL Oracle 中将 FOR 语句转换为 FORALL

在 PL/SQL 中运行 forall 循环时,是不是需要事后提交?

如何在 PL/SQL 中使用 BULK COLLECT 和 FORALL 替换 CURSOR FOR LOOP?

在 PL/SQL 的 FORALL 循环内插入

使用 PL/SQL 使用 forall 语法批量插入