不能限制存储过程参数和函数返回类型是 Oracle PL/SQL 的一个特点。也就是说,我们不能有这样一个签名的过程:
SQL> create or replace procedure my_proc (p1 in varchar2(30))
2 is
3 begin
4 null;
5 end;
6 /
Warning: Procedure created with compilation errors.
SQL> show error
Errors for PROCEDURE MY_PROC:
LINE/COL ERROR
-------- -----------------------------------------------------------------
1/34 PLS-00103: Encountered the symbol "(" when expecting one of the
following:
:= . ) , @ % default character
The symbol ":=" was substituted for "(" to continue.
SQL> create or replace procedure my_proc (p1 in varchar2)
2 is
3 begin
4 null;
5 end;
6 /
Procedure created.
SQL>
当然,我们可以使用 SUBTYPE 定义过程的参数,但 Oracle 会忽略它。函数返回类型也是如此......
SQL> create or replace package my_subtypes as
2 subtype ltd_string is varchar2(30);
3 end;
4 /
Package created.
SQL> create or replace function my_func return my_subtypes.ltd_string
2 is
3 begin
4 return lpad('a', 4000, 'a');
5 end;
6 /
Function created.
SQL> select length(my_func) from dual
2 /
LENGTH(MY_FUNC)
---------------
4000
SQL>
限制参数和返回类型的唯一方法是在存储过程中使用子类型声明变量。使用包中的变量,并将它们分配给 OUT 参数(或返回函数的变量)。
这是一种冗长的说法,您可以 DBMS_OBFUSCATION_TOOLKIT.VARCHAR2_CHECKSUM在代码中使用确信它不会阻止您的函数返回 32 个字符。
但是,它会使查找 SUBTYPE 声明的开发人员感到困惑。在最坏的情况下,这些人将使用子类型来声明他们自己的工作变量,结果如下:
SQL> declare
2 v my_subtypes.ltd_string;
3 begin
4 v := my_func;
5 end;
6 /
declare
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at line 4
SQL>
所以,最好不要使用不合适的子类型。而是声明你自己的。