【问题标题】:PL/SQL Passing a local collection into a pipelined functionPL/SQL 将本地集合传递给流水线函数
【发布时间】:2023-03-16 02:47:01
【问题描述】:

我需要将一个本地定义的表类型传递给一个函数,该函数是一个返回另一个本地定义的表类型的流水线函数。

这里是示例数据:

create table my_tab
(i NUMBER,
 n VARCHAR2(30));

 insert into my_tab values (1, 'Peter');
 insert into my_tab values (2, 'Dakshesh');
 insert into my_tab values (1, 'Maggie');
 insert into my_tab values (3, 'Madhu');
 commit;

我的代码是:

CREATE OR REPLACE PACKAGE my_pkg IS
    TYPE t_col IS RECORD(
    i NUMBER,
    n VARCHAR2(30));
    TYPE t_nested_table IS TABLE OF t_col;
    TYPE t_number IS TABLE OF NUMBER;
    FUNCTION iterate_table RETURN t_number PIPELINED;
    FUNCTION return_table(in_t_num t_number) RETURN t_nested_table PIPELINED;
     g_number t_number ;
     g_nested_number t_nested_table ;
  END my_pkg;
  /

主体:

 CREATE OR REPLACE PACKAGE BODY my_pkg IS
    FUNCTION iterate_table RETURN t_number PIPELINED IS
    BEGIN
      IF ( (g_number IS NOT NULL) AND (g_number.EXISTS (1)))
      THEN
         FOR i IN 1 .. g_number.COUNT
         LOOP
            IF g_number (i) IS NOT NULL
            THEN
               PIPE ROW (g_number (i));
            END IF;
         END LOOP;
      END IF;
      RETURN;
   EXCEPTION
      WHEN OTHERS
      THEN
         RAISE;
   END iterate_table;

   FUNCTION return_table(in_t_num t_number) RETURN t_nested_table PIPELINED IS
      l_row t_nested_table ;
      CURSOR cur_test IS
          select mt.i, mt.n 
          from my_tab mt, TABLE(iterate_table ) tab
          where mt.i = tab.column_value;
     BEGIN
         OPEN cur_test;
         FETCH cur_test BULK COLLECT into l_row;
         CLOSE cur_test;
         FOR i IN 1..l_row.COUNT
         LOOP
             PIPE ROW(l_row(i));
         END LOOP;
         RETURN;
     END return_table;
 END my_pkg;
 /

现在这段代码编译成功了,当我尝试像流水线函数一样调用它时,它给出了错误-

select * from table(my_pkg.return_table(my_pkg.t_number(1)));

错误- ORA-00902: invalid datatype 00902. 00000 - "invalid datatype" *Cause:
*Action: Error at Line: 14 Column: 41

此代码的两个先决条件是 -

  1. 集合应该都是本地定义的。

  2. 函数应该是流水线的。

救命!!

我没有收到任何关于表及其单个表的错误,因此没有外键约束。

【问题讨论】:

  • 不...这是不同的....创建表时我没有收到任何错误,并且只有一个表..没有违反约束。
  • 也.. 如果我使用匿名块和 dbms_output 实用程序打印它,我可以获得输出。
  • 你确定这是你的整个包裹吗?第 14 行似乎是 END IF;
  • 可以在这里找到一个好的解决方案stackoverflow.com/questions/2779495/…

标签: sql oracle plsql oracle12c


【解决方案1】:

在 oracle 11 中是不可能的。我不知道为什么 oracle 会抛出“无效数据类型”。 如果您将此查询放入匿名块中,您将收到PLS-00642: Local Collection Types Not Allowed in SQL Statement

如果您不想或无法创建 sql 级别的集合。解决方案是使用预定义类型。预定义集合的良好来源是Oracle Data Cartridge。将所有t_number 替换为ODCINumberList

predefined collections

【讨论】:

  • 不允许使用 sys 拥有的对象。
【解决方案2】:

在 Oracle 10 和 11 中,不能在 SQL 范围内使用已在 PL/SQL 范围内定义的集合。 In Oracle 12,你正在尝试的应该工作。

如果您想这样做,请在 SQL 范围内(而不是在包中)声明您的类型。

CREATE OR REPLACE TYPE t_col IS OBJECT(
  i NUMBER,
  n VARCHAR2(30)
);
/

CREATE OR REPLACE TYPE t_nested_table IS TABLE OF t_col;
/

CREATE OR REPLACE TYPE t_number IS TABLE OF NUMBER;
/

CREATE OR REPLACE PACKAGE my_pkg IS
  FUNCTION iterate_table RETURN t_number PIPELINED;
  FUNCTION return_table(in_t_num t_number) RETURN t_nested_table PIPELINED;
  g_number t_number ;
  g_nested_number t_nested_table ;
END my_pkg;
/

【讨论】:

  • @ShrutiJoshi 在您的问题中提及这一点会有所帮助。我已重新标记问题以包含版本。
  • 下次会注意的......但是,据我所知,到目前为止,这在任何版本中都是不可能的......此外,我的身份有很多限制允许使用,什么不允许。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-10-26
  • 2021-07-26
  • 2012-09-16
  • 2021-10-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多