【问题标题】:Oracle not resetting/reinitialising a packageOracle 不重置/重新初始化包
【发布时间】:2018-02-23 22:03:51
【问题描述】:

我有以下示例 PL/SQL 代码:

create table messages
(
  when timestamp,
  what varchar2(200)
)

create or replace package init_test

is
  procedure set(
    w varchar2
  );
  procedure report(
    msg varchar2
  );
end;

create or replace package body init_test
is
  wibble varchar2(100);

  procedure set(
    w varchar2
  ) is
  begin
    wibble := w;
    report('Setting ' || w);
  end; 

  procedure report(
    msg varchar2
  ) is
    pragma AUTONOMOUS_TRANSACTION;
  begin
    insert into messages values(current_timestamp, 'Wibble := ' || wibble);
    insert into messages values(current_timestamp, msg);
    commit;
  end;  
begin 
  report('Init called');
end; -- End of package body

begin
  init_test.set('Init test');
  init_test.report('Hello world');
  dbms_session.reset_package;
  init_test.report('Goodbye world');
end;
/

运行后,messages 包含:

23-FEB-18 08.23.24.439726000    Wibble := 
23-FEB-18 08.23.24.440028000    Init called
23-FEB-18 08.23.24.440267000    Wibble := Init test
23-FEB-18 08.23.24.440435000    Setting Init test
23-FEB-18 08.23.24.440597000    Wibble := Init test
23-FEB-18 08.23.24.440747000    Hello world
23-FEB-18 08.23.24.440947000    Wibble := Init test
23-FEB-18 08.23.24.441098000    Goodbye world

为什么“初始化调用”没有在表中出现两次?是否有替代方案可以重置并重新初始化包?

编辑

来自@XING 的回答 - 我尝试了以下方法 - 但仍然存在同样的问题。

create table messages
(
  when timestamp,
  what varchar2(200)
)


create or replace package P is
  cnt    number := 0;
  cursor c is select * from all_objects;
  procedure print_status;
  procedure report(
    msg varchar2
  );
end P;
/

create or replace package body P is
  procedure report(
    msg varchar2
  ) is
    pragma AUTONOMOUS_TRANSACTION;
  begin
    insert into messages values(current_timestamp, msg);
    commit;
  end; 

  procedure print_status is
  begin
    report('P.cnt = ' || cnt);
    if c%ISOPEN then
      report('P.c is OPEN');
    else
      report('P.c is CLOSED');
    end if;
  end;
end P;
/

begin
   P.cnt := 111;
   open p.c;
   P.print_status;
   dbms_session.modify_package_state(dbms_session.reinitialize);
   P.print_status;
end;

【问题讨论】:

  • 你的包裹体的末端在哪里?我在您的代码中找不到它。你能放吗?我也无法理解为什么你在执行一次时会期望“调用 init”两次。
  • 重置后 - 包应该重新初始化吗?
  • 是的,在dbms_session.reset_package 之后,此会话中的所有包都将被取消实例化。当你说去实例化意味着它只在使调用完成运行的 PL/SQL 调用之后释放内存、游标和包变量。要重新初始化变量,您可能需要使用 DBMS_SESSION.REINITIALIZE

标签: oracle plsql


【解决方案1】:

重置后 - 包应该重新初始化吗?

据我所知,如果您想重新初始化您的 pacakge,您可能需要 dbms_session.reinitialize 代替 dbms_session.reset_packageReinitializationRESETING 不同。重新初始化是指将所有包变量重置为其初始值并在包主体中运行初始化块(如果有)的过程,其中RESET_PACKAGE 仅在执行 PL/SQL 调用后释放内存、游标和包变量调用完成运行。

请参见下面的重新初始化示例。

create or replace package P is
  cnt    number := 0;
  cursor c is select * from emp;
  procedure print_status;
end P;
/

create or replace package body P is
  procedure print_status is
  begin
    dbms_output.put_line('P.cnt = ' || cnt);
    if c%ISOPEN then
      dbms_output.put_line('P.c is OPEN');
    else
      dbms_output.put_line('P.c is CLOSED');
    end if;
  end;
end P;
/

SQL> set serveroutput on;
SQL> begin
  2   P.cnt := 111;
  3   open p.c;
  4   P.print_status;
  5  end;
  6  /
P.cnt = 111
P.c is OPEN

PL/SQL procedure successfully completed.

SQL> begin
  2   dbms_session.modify_package_state(dbms_session.reinitialize);
  3  end;
  4  /

PL/SQL procedure successfully completed.

SQL> set serveroutput on;
SQL>
SQL> begin
  2   P.print_status;
  3  end;
  4  /
P.cnt = 0
P.c is CLOSED

PL/SQL procedure successfully completed.

【讨论】:

    猜你喜欢
    • 2021-06-03
    • 2010-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-01
    • 1970-01-01
    • 2012-01-07
    • 1970-01-01
    相关资源
    最近更新 更多