在函数包规范中定义的Oracle函数返回记录类型表

时间:2016-02-24 09:15:32

标签: oracle plsql oracle12c

我有一个函数,它获取一个字符串和分隔符作为输入参数,并将分割的字符串作为表返回。 当我运行这个功能时:

create or replace PACKAGE split_pkg AS
TYPE triplex_record IS RECORD (
                id      NUMBER,
                data    VARCHAR2(4000),
                data1   VARCHAR2(4000),
                data2   VARCHAR2(4000)
                );
TYPE triplex_tab IS TABLE OF triplex_record;
FUNCTION triplex (p_txt IN VARCHAR2, p_delimiter IN VARCHAR2) RETURN triplex_tab ;
END split_pkg;
/
create or replace PACKAGE BODY split_pkg AS
FUNCTION triplex (p_txt IN VARCHAR2, p_delimiter IN VARCHAR2)
    RETURN triplex_tab
AS
    triplex_tbl     triplex_tab := triplex_tab();
BEGIN
    FOR i IN 1..TRUNC((REGEXP_COUNT(p_txt , '[^' || p_delimiter || ']+'))/3)
    LOOP
        triplex_tbl.EXTEND;
        triplex_tbl(triplex_tbl.LAST).id := i;
        triplex_tbl(triplex_tbl.LAST).data := TRIM(REGEXP_SUBSTR(p_txt, '[^' || p_delimiter || ']+' , 1, 3 * i - 2));
        triplex_tbl(triplex_tbl.LAST).data1 := TRIM(REGEXP_SUBSTR(p_txt, '[^' || p_delimiter || ']+' , 1, 3 * i - 1));
        triplex_tbl(triplex_tbl.LAST).data2 := TRIM(REGEXP_SUBSTR(p_txt, '[^' || p_delimiter || ']+' , 1, 3 * i));
        --PIPE ROW(triplex_tbl);
    END LOOP;
    RETURN triplex_tbl;
END triplex;
END split_pkg;

我得到以下错误:

  

ORA-00902:数据类型无效

如果创建为PIPELINED函数我没有问题,我只想在PACKAGE'标题中使用RECORD TYPE定义我的TYPE,而不是在模式级别使用CREATE TYPE。怎么办?

1 个答案:

答案 0 :(得分:1)

没有看到包的问题:

SET SERVEROUTPUT ON;

DECLARE
  triplets SPLIT_PKG.triplex_tab;
BEGIN
  triplets := split_pkg.triplex( 'a1,a2,a3,b1,b2,b3,c1,c2,c3,d1', ',' );
  FOR i IN 1 .. triplets.COUNT LOOP
    DBMS_OUTPUT.PUT_LINE( triplets(i).data );
    DBMS_OUTPUT.PUT_LINE( triplets(i).data1 );
    DBMS_OUTPUT.PUT_LINE( triplets(i).data2 );
    DBMS_OUTPUT.PUT_LINE( '------' );
  END LOOP;
END;
/

<强>输出

anonymous block completed
a1
a2
a3
------
b1
b2
b3
------
c1
c2
c3
------

但是,如果要在SQL中使用结果,则需要在SQL中而不是在包中定义类型。

CREATE TYPE triplex_obj IS OBJECT (
  id      NUMBER,
  data    VARCHAR2(4000),
  data1   VARCHAR2(4000),
  data2   VARCHAR2(4000)
);

CREATE TYPE triplex_tab IS TABLE OF triplex_obj;

create or replace PACKAGE split_pkg AS
FUNCTION triplex (p_txt IN VARCHAR2, p_delimiter IN VARCHAR2) RETURN triplex_tab ;
END split_pkg;
/
SHOW ERRORS;

create or replace PACKAGE BODY split_pkg AS
FUNCTION triplex (p_txt IN VARCHAR2, p_delimiter IN VARCHAR2)
    RETURN triplex_tab
AS
    triplex_tbl     triplex_tab := triplex_tab();
BEGIN
    FOR i IN 1..TRUNC((REGEXP_COUNT(p_txt , '[^' || p_delimiter || ']+'))/3)
    LOOP
        triplex_tbl.EXTEND;
        triplex_tbl(triplex_tbl.LAST) := triplex_obj(
          i,
          TRIM(REGEXP_SUBSTR(p_txt, '[^' || p_delimiter || ']+' , 1, 3 * i - 2)),
          TRIM(REGEXP_SUBSTR(p_txt, '[^' || p_delimiter || ']+' , 1, 3 * i - 1)),
          TRIM(REGEXP_SUBSTR(p_txt, '[^' || p_delimiter || ']+' , 1, 3 * i - 0))
        );
    END LOOP;
    RETURN triplex_tbl;
END triplex;
END split_pkg;
/
SHOW ERRORS;

然后:

SET SERVEROUTPUT ON;

DECLARE
  triplets triplex_tab;
BEGIN
  triplets := split_pkg.triplex( 'a1,a2,a3,b1,b2,b3,c1,c2,c3,d1', ',' );
  FOR i IN 1 .. triplets.COUNT LOOP
    DBMS_OUTPUT.PUT_LINE( triplets(i).data );
    DBMS_OUTPUT.PUT_LINE( triplets(i).data1 );
    DBMS_OUTPUT.PUT_LINE( triplets(i).data2 );
    DBMS_OUTPUT.PUT_LINE( '------' );
  END LOOP;
END;
/

提供与上面相同的输出,但您也可以这样做:

SELECT *
FROM   TABLE( split_pkg.triplex( 'a1,a2,a3,b1,b2,b3,c1,c2,c3,d1', ',' ) );

输出:

id      Data    Data1   Data2
------- ------- ------- -------
1       a1      a2      a3
2       b1      b2      b3
3       c1      c2      c3