PL/SQL包的begin/end块中的代码何时执行?

5
我有一段类似于以下代码片段的PL/SQL代码:
create or replace
package body MY_PACKAGE as
    type array_type is table of char index by varchar2(1);
    lookup_array array_type;

    function DO_SOMETHING(input nvarchar2) 
    return varchar2 as
    begin
        -- Do something here with lookup_array
    end DO_SOMETHING;

    procedure init_array as
    begin
        lookup_array('A') := 'a';
        lookup_array('B') := 'b';
            -- etc
    end init_array;
begin
    init_array;
end MY_PACKAGE;

它使用静态查找数组来处理提供给DO_SOMETHING的数据。我的问题是,init_array是何时被调用和lookup_array被加载到内存中的?在包编译时吗?第一次调用时吗?它会被多次调用吗?有更好的实现静态查找数组的方法吗?
谢谢!

那无法编译 - 你有包的主体,但没有 spc。 - OMG Ponies
是的,我知道;它也无法编译,因为DO_SOMETHING函数是空的。这只是一个片段,让大家了解我想做什么。 - Kevin Babcock
一个有效的例子会更少分散注意力。 - OMG Ponies
2
更少不贡献于讨论的注释也会减少分散注意力。 - Kevin Babcock
2个回答

5

4

Q1. "init_array何时被调用,lookup_array何时加载到内存中?在包编译时吗?在第一次调用时吗?它会被多次调用吗?"

只要包中的任何函数或过程被调用,就会调用init_array - 即"即时"调用。每当包状态丢失时,它都会被调用(即可能在每个会话中被调用多次)。

这对于包状态丢失的情况有影响 - 例如,当某人重新编译包时。在这种情况下,发生以下序列:

  1. 您的会话调用do_something - 首先调用init_array,然后执行do_something - 您的会话现在具有一些分配给数组的PGA内存。

  2. 我的会话重新编译包。此时,为该包分配的您的会话内存被标记为“无效”。

  3. 您的会话再次调用do_something - Oracle检测到您的会话内存已标记为无效,并发出ORA-04061“xxx的现有状态已失效”。

  4. 如果您的会话再次调用do_something,则会在没有错误的情况下进行 - 它首先调用init_array,然后执行do_something

Q2. "是否有更好的实现静态查找数组的方法?"

我认为这种方法没有什么实际问题,只要您考虑到上述行为即可。

在某些情况下,我看到人们将init调用放在需要该数组的每个函数/过程的开头 - 即每当调用do_something时,它都会检查是否需要初始化,如果是,则调用init_array。这种方法的优点是您可以自定义init_array以仅初始化函数/过程需要的位 - 如果init_array执行了大量工作,这可能是有利的 - 这可能有助于避免每个会话的一次大启动开销。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接