我们可以在变量中使用 default 并在 plsql 中调用函数吗?

can we use default in a variable with function call in plsql?

我有一个包裹,里面我声明g_suppress_all_xlog BOOLEAN := fnc_Suppress() DEFAULT NULL;

FUNCTION fnc_suppress
   RETURN BOOLEAN
IS
   v_ret       BOOLEAN := FALSE;                                  -- assume NO
   v_suppress  VARCHAR2 (3);
BEGIN
   SELECT VALUE
     INTO v_suppress
     FROM server_config
    WHERE name = 'Suppress_All_Xlog';

   IF (v_suppress = 'YES')
   THEN
      v_ret := TRUE;
   END IF;

   RETURN v_ret;
EXCEPTION
   WHEN OTHERS
   THEN
      prc_exception ();
END fnc_suppress;

我收到错误,如何默认为 null 并替换为函数值。

你只需要

g_suppress_all_xlog BOOLEAN := fnc_Suppress();

不要明确地设置为 NULL;你什么都不说,反正就是NULL

SQL> create or replace package pkg_Test as
  2    procedure p_test;
  3    g_suppress_all_xlog boolean;
  4  end;
  5  /

Package created.

SQL> create or replace package body pkg_Test as
  2    procedure p_test is
  3    begin
  4      dbms_output.put_line('Variable''s value = ' ||
  5        case when g_suppress_all_xlog then 'true'
  6             when not g_suppress_all_xlog then 'false'
  7             else 'null'
  8        end);
  9    end;
 10  end;
 11  /

Package body created.

SQL> exec pkg_test.p_test;
Variable's value = null

PL/SQL procedure successfully completed.

SQL>

fnc_suppress 不能属于您声明此函数的同一个包,因此 - 它必须是一个独立函数或另一个包的一部分。

SQL> create or replace package pkg_Test as
  2    function fnc_suppress_in_pkg return boolean;
  3    procedure p_test;
  4    g_suppress_all_xlog boolean := fnc_suppress_in_pkg();
  5  end;
  6  /

Warning: Package created with compilation errors.

SQL> show err
Errors for PACKAGE PKG_TEST:

LINE/COL ERROR
-------- -----------------------------------------------------------------
4/23     PL/SQL: Declaration ignored
4/23     PLS-00492: variable or constant initialization may not refer to
         functions declared in the same package

SQL>

最后:

SQL> create or replace function fnc_suppress return boolean
  2    is
  3  begin
  4    return true;
  5  end;
  6  /

Function created.

SQL> create or replace package pkg_Test as
  2    procedure p_test;
  3    g_suppress_all_xlog boolean := fnc_suppress;
  4  end;
  5  /

Package created.

SQL> create or replace package body pkg_Test as
  2    procedure p_test is
  3    begin
  4      dbms_output.put_line(case when g_suppress_all_xlog then 'true' else 'false' end);
  5    end;
  6  end;
  7  /

Package body created.

SQL> exec pkg_test.p_test;
true

PL/SQL procedure successfully completed.

SQL>

fnc_suppress_in_pkg() 可以在包 pkg_test 中。它只是不能用于规范中的分配,它还不存在。似乎 OP 想要初始化变量 g_suppress_all_xlog 在执行任何 function/procedure 之前初始化。这可以通过包体的 initialization section 来完成。 (注意:我的游乐场有 table config_settings table 可用,所以我用它代替了 server_config)

create or replace package pkg_test as
    g_suppress_all_xlog boolean;

    procedure prc_exception;
    function fnc_suppress return boolean;
    -- Other procedure/functions declared here. 
end  pkg_test;      

create or replace package body pkg_test as
   procedure prc_exception is
   begin 
       null;
   end prc_exception;

   function fnc_suppress 
      return boolean
   is
      v_suppress  varchar2 (3);
   begin
      select setting
        into v_suppress
        from config_settings
       where name = 'Suppress_All_Xlog';

      return (v_suppress = 'YES');
   exception
      when others
      then
         prc_exception ();
   end fnc_suppress;

   -- Other procedure/functions defined here. 

begin   -- this the package initialization. It executes 1 time when the package is first loaded.
  g_suppress_all_xlog := fnc_suppress;
end pkg_test; 


--  Test with direct reference to g_suppress_all_xlog 
    insert into config_settings(name,setting ) values('Suppress_All_Xlog', 'YES');
    declare
       setting varchar2(30); 
    begin
       if pkg_test.g_suppress_all_xlog 
          then dbms_output.put_line('Xlog being suppressed');
          else dbms_output.put_line('Xlog being written');
       end if;
    end; 

恕我直言>> 但是声明变量 g_suppress_all_xlog 是规范是不好的做法。这使得同一会话中的任何进程都可以访问它以进行读取(还不错)和写入(不好)。一个更好的过程是在主体中声明它,这样就不能直接访问它。我知道它的目的是每次都必须 select,所以添加另一个函数来简单地 returns 它的值。