Oracle 中调用本地程序的限制?

Posted

技术标签:

【中文标题】Oracle 中调用本地程序的限制?【英文标题】:Limitation in Oracle to call a local procedure? 【发布时间】:2021-10-10 02:39:30 【问题描述】:

我已经在 SQL*PLUS 中执行了下面的块,它成功地执行了整个块。 奇怪的是,它只在表中插入了 32768 个唯一值,其余 7232 是重复的。

请注意,我们必须在不使用循环的情况下手动调用本地过程 40k 次。

/*
-- @Hello
-- please create this test table
-- on your database schema

CREATE TABLE my_table (
   num       NUMBER,
   upd_dt   DATE DEFAULT SYSDATE
)
/
*/

DECLARE
   TYPE my_tp IS TABLE OF my_table%ROWTYPE;
   my_nest_t my_tp := my_tp ();

   PROCEDURE add (
      p_num   IN      NUMBER
   )
   AS
   BEGIN
      my_nest_t.EXTEND;
      my_nest_t (my_nest_t.LAST) := NULL;
      my_nest_t (my_nest_t.LAST).num := p_num;
   END add;
BEGIN
   add (1);
   add (2);
   add (3);
   add (4);
   /*
   -- @Hello
   -- this way manually write the call to
   -- the local proc 40000 times
   -- I used CONNECT BY LEVEL to generate the script
   -- SELECT ' add (p_num=>' || level || ');' FROM DUAL CONNECT BY LEVEL < 40001
   -- use this query only to generate the 40k rows of code
   */
   add (39999);
   add (40000);
   
   IF my_nest_t.COUNT < 40000 THEN
      RAISE_APPLICATION_ERROR (-20001, '@Hello - please call PROCEDURE add 40000 times as mentioned above');
   END IF;

   FORALL i IN 1.. my_nest_t.COUNT
      INSERT INTO my_table (num)
      VALUES (my_nest_t (i).num);
   COMMIT;
END;
/

/*
-- @Hello
*/

-- 40000, 32768
SELECT COUNT (1),
               COUNT (DISTINCT num)
FROM    my_table

【问题讨论】:

您是否在表上有一个触发器,该触发器从具有maxvalue 32768cycle 的序列中分配/覆盖提供的num 值?比较 this 和 this。你没有提出你的例外,所以问题不在于add() 或对它的调用;所以插入必须是问题。 (您也可以使用批量插入或不使用任何 PL/SQL...) 正如您所确认的,这种情况不会触发;如果您使用的是 11gR1(例如 11.1.0.7),您可能遇到了错误,可能是 forall; this looks like a possibility 例如。如果您为带有单独插入的for 循环更改它,您会得到正确的结果吗?您似乎在暗示问题仅出现在大量单独的调用中,而不是在循环中调用,但在插入之前集合是否不正确尚不清楚。 “我们必须手动调用本地程序 40k 次”...真的吗?您手动调用该程序 40k 次?比如,你按下某个按钮 40k 次?难以置信。无论如何 - 无论调用什么程序,你确定它会执行 40k 次吗? @MarcinWroblewski - 来自其他 cmets,仅当匿名块对本地 add() 过程有 40000 次单独调用时才会出现此问题;这就是OP所说的“手动”的意思。显然,当从循环中进行 40000 次调用时,它不会发生。当然,这没有多大意义。 我第一次没有仔细阅读。我现在对插入的实际值很好奇。例如SELECT num, count() FROM my_table GROUP BY num HAVING count() > 1 或 SELECT max(num), min(num) FROM my_table。还有 32768 = 32 * 1024 = 2^15,这可能不是巧合。无法在 19c 上重现该问题。 【参考方案1】:

我在 12.1 版上运行良好。

我相信添加过程的调用之间存在重复。

这里,我是如何为测试生成这些的

select 'add(' || level || ');' from dual connect by level <= 40000

然后我将它们复制到 plsql 块并启动。之后您的检查查询

SELECT COUNT (1), COUNT (DISTINCT num)
  FROM    ek_test;

两个列都显示 40000。

所以我的回答是,请检查所有这 4 万个程序调用并查找重复项。

【讨论】:

您好,感谢您的回复。但是,是的,我使用了相同的方法(CONNECT BY LEVEL SELECT ' add (p_num=>' || level || ');'从双连接级别 @ShintoJoy 抱歉没有看到。我已经尝试过使用您的代码,但所有列仍然等于 40000。您能否在 dbfiddle 上重现它? @ShintoJoy 如果您发现任何问题,请告诉我。这是一个有趣的案例 当然,我第一次在 *** 上发帖,因为这对我来说太奇怪了,我很想知道这个问题的任何线索。感谢您的出现并提供了一些启发。我一定会及时通知你的。 ??

以上是关于Oracle 中调用本地程序的限制?的主要内容,如果未能解决你的问题,请参考以下文章

oracle数据库中,存储过程中 %rowtype 类型的用法有啥限制吗?

iOS 应用程序在本地搜索中受到限制

限制 Oracle 创建编译错误程序

Oracle 中 varchar2 PL/SQL 子程序参数的大小限制是多少?

限制 Node.js 中的异步调用

限制从 Oracle 中的 SQL 查询返回的记录