【问题标题】:Global variable size in Oracle packageOracle 包中的全局变量大小
【发布时间】:2013-04-14 06:05:45
【问题描述】:

如何根据函数的参数大小为oracle包中Varchar2类型的全局变量设置大小。

CREATE OR REPLACE PACKAGE Test 
AS

   g_lastname Varchar2(15);
   FUNCTION search( p_lastname IN varchar2);

END;

CREATE OR REPLACE PACKAGE BODY Test
AS
    FUNCTION search(p_lastname IN VARCHAR2) return VARCHAR2 
    IS
    BEGIN
        g_lastname := p_lastname;
        return g_lastname;
    END;
END;

这里的问题是如果 p_lastname 的大小超过 15 就会出错。

【问题讨论】:

  • @APC 我在将 p_lastname 的值分配给 g_lastname 时询问了这个问题,它给了我 ORA-06502: PL/SQL: numeric or value error: string buffer too small as error。这应该是什么原因,这里 p_lastname 的大小是 varchar2(1)。谢谢。

标签: oracle package global-variables


【解决方案1】:

您不能,因为函数参数可以是varchar2 的任意大小,并且直到运行时才知道。

如果您知道稍后将如何使用该值,那么您可以根据表格列对其进行约束;因此,如果它最终将用于从表people 中选择,您可以将其声明为:

    g_lastname people.last_name%type;

您也可以在函数声明中使用该语法:

    FUNCTION search(p_lastname IN people.last_name%type) return VARCHAR2

...虽然这实际上并没有限制可以传入的值的大小;如果p_lastname 的值太大,分配仍然会失败。可以说,在这种情况下,它必须在某个时候失败,在这里它可能比你稍后在select 中尝试使用它时更好。但它在代码中提供了一些一致性,并且 (IMO) 显示了全局和参数的意图,这对于以后的维护和故障排除很有用。

如果您只是想避免错误,如果传递的值太长,您可以选择截断:

        g_lastname := substr(p_lastname, 1, 15);

... 或先测试长度,但幻数并不完全理想(如果您更改 g_lastname 的定义,您必须记住查找和替换任何依赖该长度的内容);或者捕获并处理异常。

否则,仅仅声明它比你想象的要大并没有太大的缺点,最多:

    g_lastname varchar2(32767);

虽然您可能会想出一个实际的更小的最大长度,但该值将永远需要(当然,除非有人更改要求!)。 documentation 讨论大变量的内存分配。

【讨论】:

  • 用最大尺寸声明变量会浪费内存,不是吗?
  • %type 在我的情况下也没有帮助。 :(
  • @eatSleepCode - 不是according to the documentation,没有。如果你能找到一个你认为安全的限制,你可以设置一个更现实的限制,但你可能通过声明为 >= 4000(字节)来节省内存。无论如何我都会留下 %type 位,以防它对其他人有用...
【解决方案2】:

"%type 对我的情况没有帮助。"

这很不寻常。大多数在 PL/SQL 程序之间传递的数据来自或最终出现在数据库表中。所以最佳实践是通过引用适当列的声明来定义变量和参数。

但是,对于真正不映射到任何表列的数据项,存在子类型声明。您可以在任何地方定义这些,但将所有声明组织在一个地方会很有帮助:

create or replace package types as
    subtype name_t is varchar2(15);
end;
/

您可以像这样在您的程序中使用它:

CREATE OR REPLACE PACKAGE Test 
AS

   FUNCTION search( p_lastname IN types.name_t) return types.name_t;

END;

(我将 g_lastname 从规范移至正文,因为将包变量封装在正文中并仅通过打包过程访问它们是个好主意。)

CREATE OR REPLACE PACKAGE BODY Test
AS

    g_lastname types.name_t;

    FUNCTION search( p_lastname IN types.name_t) return types.name_t 
    IS
    BEGIN
        g_lastname := p_lastname;
        return g_lastname;
    END;
END;

使用子类型的好处是只有一个地方可以定义类型的精度。如果您需要 20 个字符的名称,只需更改该包规范中的声明,更改就会传播到所有引用程序。

【讨论】:

  • CREATE OR REPLACE PACKAGE Test AS g_lastname Varchar2(15); FUNCTION search( p_lastname IN varchar2); END; CREATE OR REPLACE PACKAGE BODY Test AS FUNCTION search(p_lastname IN VARCHAR2) return VARCHAR2 IS BEGIN g_lastname := p_lastname; return g_lastname; END; END; 这里我得到 ORA-06502: PL/SQL: numeric or value error: string buffer too small exception while assignment the value to g_lastname 实际上 p_lastname 的大小为 1 字节。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-03-28
  • 1970-01-01
  • 2023-02-11
  • 2021-12-18
  • 2012-09-17
  • 2012-03-31
  • 1970-01-01
相关资源
最近更新 更多