9

这是我编写的存储过程。在这个过程中,“p_subjectid”是一个从前端传递的数字数组。

PROCEDURE getsubjects(p_subjectid subjectid_tab,p_subjects out refCursor) 
       as

       BEGIN

            open p_subjects for select * from empsubject where subject_id in
            (select column_value from table(p_subjectid));
            --select * from table(cast(p_subjectid as packg.subjectid_tab))
      END getsubjects;

这是我得到的错误。

Oracle error ORA-22905: cannot access rows from a non-nested table item OR

正如我在不同的帖子中看到的那样,我尝试在下面的评论中给出的表函数中转换“cast(p_subjectid as packg.subjectid_tab)”。但我收到另一个错误:ORA-00902: invalid datatype

这就是“subjectid_tab”的定义。

type subjectid_tab is table of number index by binary_integer;

谁能告诉我错误是什么。我的程序有什么问题吗?

4

5 回答 5

13

您必须按照 ammoQ 的建议在“数据库级别”声明类型:

CREATE TYPE subjectid_tab AS TABLE OF NUMBER INDEX BY binary_integer;

而不是在 PL/SQL 中声明类型。如果只在 PL/SQL 块中声明类型,SQL“引擎”将无法使用它。

于 2009-09-10T10:55:23.340 回答
3

Oracle 有两个执行范围:SQL 和 PL/SQL。当您使用SELECT// INSERT( UPDATEetc) 语句时,您正在 SQL 范围内工作,并且在 Oracle 11g 及更低版本中,您不能引用在 PL/SQL 范围内定义的类型。(注意:Oracle 12 对此进行了更改,因此您可以引用 PL/SQL 类型。)

TYPE subjectid_tab IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;

是一个关联数组,只能在 PL/SQL 范围内定义,因此不能在 SQL 语句中使用。

您想要的是使用以下方法在 SQL 范围内定义一个集合(不是关联数组):

CREATE TYPE subjectid_tab IS TABLE OF NUMBER;

注意:您不需要INDEX BY集合的子句。

然后你可以这样做:

OPEN p_subjects FOR
  SELECT *
  FROM   empsubject
  WHERE  subject_id MEMBER OF p_subjectid;

或者

OPEN p_subjects FOR
  SELECT *
  FROM   empsubject
  WHERE  subject_id IN ( SELECT COLUMN_VALUE FROM TABLE( p_subjectid ) );
于 2018-04-30T08:43:35.547 回答
2

我昨天刚遇到这个问题。

宣布
  类型 number_table 是数字表;
  result_ids number_table := number_table();
开始
  /* .. 一堆成功使用我的类型的代码 */

  打开 ?作为
  选择 *
  FROM TABLE(CAST(result_ids AS number_table)); /* 轰!*/
结尾;

当从 java 例程调用时,这两种方式都失败了。我发现这是因为 number_table 类型没有以可导出的方式定义,不能从数据库中运出。该类型在例程内部工作得很好。但是,一旦您尝试执行以任何方式引用它的可返回记录集(包括 IN 子句?!?),您就会得到一个未定义的数据类型。

所以解决方案真的是CREATE TYPE myschema.number_table IS TABLE OF NUMBER;然后从你的块中删除类型声明并使用模式级别声明。使用模式限定符来引用类型,以确保您使用的是正确的类型。

于 2009-05-27T19:10:05.973 回答
2

这是一个很好的解决方案。如果您转换的类型在 pl/sql 块的 DECLARE 部分中,则不能使用 table(cast())。你真的需要使用 CREATE TYPE my_type [...]。否则,它会抛出“cannot fetch row[...]”异常。

于 2010-02-18T16:08:53.727 回答
1

您必须转换管道查询的结果,以便:

如果您的流水线函数返回 varchar2 的行类型,则定义一个类型(例如)

CREATE OR REPLACE TYPE char_array_t is VARRAY(32) of varchar2(255);
select * from table(cast(fn(x) as user_type_t ) );

现在可以工作了。

于 2009-05-26T11:39:57.110 回答