2013-04-12 47 views
0

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

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那么它会给出错误。

+0

@APC我将p_lastname的值赋给g_lastname的时候有问题,它给了我ORA-06502:PL/SQL:数字或值的错误:字符串缓冲区太小,错误。这应该是什么原因,这里p_lastname的大小是varchar2(1)。 谢谢。 – eatSleepCode

回答

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讨论关于大变量的内存分配。

+0

用最大尺寸声明变量会浪费内存,不是吗? – eatSleepCode

+0

对于我来说%的类型也没有帮助。 :( – eatSleepCode

+2

@eatSleepCode - 不是[根据文档](http://docs.oracle.com/cd/E11882_01/appdev.112/e25519/datatypes.htm#CIHEDDFG),no。您可以设置一个更现实的限制如果你能找到一个你认为当然是安全的,但是你可以通过声明> = 4000(字节)来节省内存。我会留下%类型的位以防其他人使用... –

1

"%type is not helpful in my case."

这很不寻常。在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个字符的名称,只需更改该软件包规范中的声明,并将更改传播到所有参考程序。

+0

' CREATE OR REPLACE PACKAGE测试AS g_lastname Varchar2(15); FUNCTION search(p_lastname IN varchar2); END; CREATE OR REPLACE PACKAGE BODY测试AS功能搜索(p_lastname IN VARCHAR2)返回VARCHAR2 IS BEGIN g_lastname:= p_lastname; return g_lastname; END; END;' 这里我得到的ORA-06502:PL/SQL:数值或值错误:字符串缓冲区太小异常,同时分配值为g_lastname实际上p_lastname大小为1字节。 – eatSleepCode