何时执行PL / SQL包开始/结束块之间的代码?

时间:2009-11-24 20:20:59

标签: plsql oracle10g

我的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加载到内存中?什么时候编译包?什么时候第一次打电话?是不是一次被召唤?有没有更好的方法来实现静态查找数组?

谢谢!

2 个答案:

答案 0 :(得分:5)

您可以参考此链接: http://www.dba-oracle.com/plsql/t_plsql_lookup_tables.htm

“这意味着在程序包初始化期间执行该过程。因此,在会话的生命周期中,除非需要刷新缓存的表,否则永远不会手动调用该过程。”

答案 1 :(得分: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

  5. <强> Q2。 “有没有更好的方法来实现静态查找数组?”

    我认为这种方法没有任何实际问题,只要你考虑上述行为。

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