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 32768
和cycle
的序列中分配/覆盖提供的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 类型的用法有啥限制吗?