create or replace package pkg is
v_num number := pkg_two.getnum_two;
function getnum return number;
end;
create or replace package pkg_two is
v_num_two number := 1;
function getnum_two return number;
end;
create or replace package body pkg is
function getnum return number is
begin
return v_num;
end;
end;
create or replace package body pkg_two is
function getnum_two return number is
begin
return v_num_two;
end;
begin
dbms_lock.sleep(10);
end;
现在这是怪异的行为。我在sqlplus中运行以下代码,并在5秒钟后中断它:
declare
v_number number;
begin
select pkg.getnum into v_number from dual;
dbms_output.put_line('output: ('||v_number||')');
end;
这种中断会抛出ORA-01013。然后,我再次运行它,只有几毫秒后,我得到了:
output: ()
这很奇怪,因为在12c中,应将软件包设置为初始化后,一旦初始化完成,如我在本文中所示:https://rogertroller.com/2018/05/05/05/16/package-initialization-initialization-changes-changes -bet-bet-bet-oracle-11g-and-Oracle-12c/
奇怪的是,如果我将“选择为”替换为“:=”行为如文章所述:
declare
v_number number;
begin
v_number := pkg.getnum;
dbms_output.put_line('output: ('||v_number||')');
end;
在执行相同的runnig过程后,我得到了两次(第二秒后10秒后):
output: (1)
是否有人请解释是否期望这种行为?如果是这样,可以在不使用“选择”子句的情况下发生吗?
指定它最初在12cr1中更改。它可能在这两个版本,在18C或19C中或两者之间的一些补丁之间发生了进一步的变化。您尚未说过哪个版本和补丁集,您会看到行为的差异。
任何人...版本执行:
v_number := pkg.getnum;
the的表现会按照您的期望,并符合文章所说的话。该版本完全是PL/SQL-您正在调用软件包函数并将其返回值直接分配给PL/SQL变量,因此不涉及SQL。
select pkg.getnum into v_number from dual;
表现方式有所不同(对您而言,但在19C中却没有),但在PL/SQL和SQL之间具有上下文切换。
select into...
基本上是从PL/SQL退出以执行SQL语句,并将结果返回到PL/SQL变量中。 (我想,如果您直接在SQL中进行
select pkg.getnum from dual
,而没有匿名块?)
ssuggests最初对初始化行为的变化进行了不同的处理方式。无论是使用什么机制,即可在您的会话中保留包裹非初始化(或非事物的),或者在PL/SQL上下文中看到的情况时,在您的会话中似乎适用于该状态。从SQL上下文中,这种早期迭代似乎忽略了同一件事。后来的补丁程序或版本将其完善,以在两种情况下都以相同的方式工作。 (无论如何 - 错误34969407表明它可能仍然不完全一致。)确切知道何时更改会很有趣。
这必然是猜测,部分是因为我没有12c dB可以再次测试,但也因为我看不到有关它的变化或内部工作方式的任何细节 - 不是我期望的 - 或任何该区域的文档变化。
由于它已被修复或至少在以后的版本中进行了修复,所以我不会说行为的差异是“预期的”,因为它看起来并不是故意的。但是,鉴于您看到的是,我希望在12CR1和一些以后的版本/补丁程序中看到它,但在最近的版本中也没有。即使那样,也可能只有在涉及上下文开关时。