【问题标题】:Oracle function return table of record type that defined in package specification包规范中定义的记录类型的Oracle函数返回表
【发布时间】:2016-02-24 09:15:31
【问题描述】:

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

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 函数,我没有问题,我只想使用 RECORD TYPE 在 PACKAGE 的标头中定义我的 TYPE,而不是使用 CREATE TYPE 在架构级别。怎么能这样?

【问题讨论】:

  • 你从哪里得到错误?编译包体时?什么时候调用函数?你是如何调用函数的?
  • @Justin Cave ,包编译没有任何错误,运行时出现错误 'SELECT * FROM TABLE(SPLIT_PKG.TRIPLEX('sample text' , ',') );'
  • 我怀疑你不能从这里到达那里。这篇文章stevenfeuersteinonplsql.blogspot.com/2015/04/… 对您的选项进行了很好的概述。根据您要完成的具体任务,可能有替代方法来构建您的代码(包括填充本地集合并将其传递给 table 函数),但很难猜测这些替代方法是否适合您。我强烈建议您只在 SQL 中定义类型。
  • @Justin Cave ,如果我用“CREATE OR REPLACE TYPE...”定义我的过程和函数中需要的所有类型,那会令人困惑,所以我想在其中定义它们中的每一个他们的包头。
  • 那么权衡你不能在纯SQL语句中使用它们。如果您的 SQL 语句位于 PL/SQL 块中,您可以定义集合类型的局部变量,调用函数来填充该集合,然后将该集合传递给 table 函数(这是 12.1 中的新功能)。

标签: oracle plsql oracle12c


【解决方案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

【讨论】:

  • 非常感谢,我知道如果我在 SQL 级别定义 TYPE 它将起作用,但我不想在 SQL 级别定义它们,我只需要在包头定义它们并成为能够像 ...FROM TABLE(...) 一样查询它们
  • 你不能 - 如果你想在 SQL 中使用它们,你需要在 SQL 级别定义 TYPEs - 你可以在 SQL 或包 (PL/SQL) 级别定义它们如果你想在 PL/SQL 中使用它们。
猜你喜欢
  • 1970-01-01
  • 2019-09-17
  • 1970-01-01
  • 2017-01-28
  • 2015-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多