我们可以在PLSQL中使用表类型参数作为默认的null参数吗?

时间:2017-06-22 11:23:24

标签: oracle plsql

我的记录类型如下,

TYPE x_Rec IS RECORD(
   master_company          x_tab.master_company%TYPE,
   report_trans_type       x_tab.report_trans_type%TYPE,
   balance_version_id      x_tab.balance_version_id%TYPE,  
   reporting_entity        x_tab.reporting_entity%TYPE,
   year_period_from        x_tab.year_period%TYPE,
   year_period_to          x_tab.year_period%TYPE,
   journal_id              x_tab.journal_id%TYPE,
   row_id                  x_tab.row_id%TYPE); 

我使用此记录创建了一个表类型:

TYPE x_rec_tab IS TABLE OF x_Rec INDEX BY PLS_INTEGER;

我想在过程中将此表类型用作默认的null参数。

PROCEDURE x_Balance___(x_param IN NUMBER,
                       x_rec_  IN x_rec_tab default null)
IS
BEGIN
...My code
END;

它提供以下错误消息

  

PLS-00382:表达式类型错误

4 个答案:

答案 0 :(得分:1)

您不能使用an associative array执行此操作,因为never be null可以使用don't have constructors。如果您尝试将null分配给类型为x_rec_tab的变量,则会出现相同的错误。它们也varray,因此您不能使用空集合。

您可以nested table或更有效地针对您的情况执行此操作"No 'Access-Control-Allow-Origin' header is present on the requested resource"

create or replace package p42 as

TYPE x_Rec IS RECORD(
   master_company          x_tab.master_company%TYPE,
   report_trans_type       x_tab.report_trans_type%TYPE,
   balance_version_id      x_tab.balance_version_id%TYPE,  
   reporting_entity        x_tab.reporting_entity%TYPE,
   year_period_from        x_tab.year_period%TYPE,
   year_period_to          x_tab.year_period%TYPE,
   journal_id              x_tab.journal_id%TYPE,
   row_id                  x_tab.row_id%TYPE); 

 -- no index-by clause, so nested table not associative array
TYPE x_rec_tab IS TABLE OF x_Rec;

end p42;
/

Package P42 compiled

show errors

No errors.


create or replace package body p42 as

PROCEDURE x_Balance___(x_param IN NUMBER,
                       x_rec_  IN x_rec_tab default null)
IS
BEGIN
  --...My code
  null;
END;

PROCEDURE dummy IS
  l_rec_tab x_rec_tab;
BEGIN
  l_rec_tab := null;
END;

end p42;
/

Package Body P42 compiled

show errors;

No errors.

您也可以默认使用空集合:

PROCEDURE x_Balance___(x_param IN NUMBER,
                       x_rec_  IN x_rec_tab default x_rec_tab())
IS
...

如果您有其他代码依赖于类型为关联数组,那么这对您没有多大帮助。

答案 1 :(得分:0)

旧问题但仍有帮助。 您可以创建一个函数:

function empty_tab
return x_rec_tab
as 
  l_tab x_rec_tab;
begin

  return l_tab;

end empty_tab;  

这样你可以(注意 empty_tab 用作默认参数):

PROCEDURE x_Balance___(x_param IN NUMBER,
                       x_rec_  IN x_rec_tab default empty_tab)
IS
BEGIN
...My code
END;

答案 2 :(得分:0)

我通过在过程签名中使用CAST(null为 your_type /)来解决此问题。

例如,在您的情况下,它将是这样的:

程序x_Balance(x_param IN NUMBER,                      x_rec_ IN x_rec_tab默认强制转换(null为x_rec_tab)

然后,在该过程中,您只需要使用count方法检查x_rec_是否包含元素。

这种方式适合我。

答案 3 :(得分:0)

这是@ManuelPerez回答的重复,但我只是觉得可以更好地解释它。

创建此过程,将可选变量转换为数据类型,如下所示:

CREATE OR REPLACE PROCEDURE Test_Procedure (
   txt_          IN  VARCHAR2,
   col_formats_  IN  dbms_sql.varchar2a DEFAULT cast(null as dbms_sql.varchar2a) )
IS BEGIN
   Dbms_Output.Put_Line (txt_);
   FOR i_ IN 1 .. 10 LOOP
      IF col_formats_.EXISTS(i_) THEN
         Dbms_Output.Put_Line (i_ || ' Exists');
      ELSE
         Dbms_Output.Put_Line (i_ || ' DOES NOT Exist');
      END IF;
   END LOOP;
END Test_Procedure;

之所以超过公认的答案,是因为它不需要您更改传入变量的数据类型。根据您的情况,您可能没有灵活性。

如果您有一个变量来填充过程,则现在这样调用过程:

DECLARE
   txt_   VARCHAR2(100) := 'dummy';
   arr_   dbms_sql.varchar2a;
BEGIN
   arr_(4) := 'another dummy';
   Test_Procedure (txt_, arr_);
END;

或者如果不这样做,就这样:

DECLARE
   txt_   VARCHAR2(100) := 'dummy';
BEGIN
   Test_Procedure (txt_);
END;

您的输出将如下所示:

dummy
1 DOES NOT Exist
2 DOES NOT Exist
3 DOES NOT Exist
4 Exists
5 DOES NOT Exist
6 DOES NOT Exist
7 DOES NOT Exist
8 DOES NOT Exist
9 DOES NOT Exist
10 DOES NOT Exist