Oracle错误ORA-22905:无法访问非嵌套表项的行

时间:2009-05-22 04:32:40

标签: oracle10g

这是我写的存储过程。在这个过程中,“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;

任何人都可以告诉我错误是什么。我的程序有什么问题。

5 个答案:

答案 0 :(得分:11)

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

CREATE TYPE subjectid_tab AS TABLE OF NUMBER INDEX BY binary_integer;

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

答案 1 :(得分:2)

这是一个很好的解决方案。 如果您转换的类型位于pl / sql块的DECLARE部分,则不能使用表(cast())。 你真的需要使用CREATE TYPE my_type [...]。否则,它将抛出“无法获取行[...]”异常。

答案 2 :(得分:2)

我昨天刚遇到这个问题。

DECLARE 
  TYPE number_table IS TABLE OF NUMBER;
  result_ids number_table := number_table();
BEGIN
  /* .. bunch of code that uses my type successfully */ 

  OPEN ? AS 
  SELECT * 
  FROM TABLE(CAST(result_ids AS number_table)); /* BOOM! */
END;

从java例程调用时,前面描述的两种方法都失败了。我发现这是因为类型number_table没有以可导出的方式定义,而不是从数据库中运出。该类型在常规内部工作得很好。但是,只要您尝试执行以任何方式引用它的可返回记录集(包括IN子句?!?),您将获得未定义的数据类型。

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

答案 3 :(得分:1)

Oracle有两个执行范围:SQL和PL / SQL。当您使用SELECT / INSERT / UPDATE(etc)语句时,您正在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 ) );

答案 4 :(得分: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 ) );

现在可以使用了。