ORA-22905 - 使用select语句查询表类型时

Tom*_*Tom 9 sql oracle plsql

 DECLARE
 TYPE record_AB IS RECORD
   (
      AA              VARCHAR2 (16 BYTE),
      BB    VARCHAR2 (16 BYTE)
   );

  TYPE type_tab_AB IS TABLE OF record_AB
                        INDEX BY BINARY_INTEGER;

  tab_AB   type_tab_AB;

  BEGIN
   SELECT *
    BULK COLLECT INTO tab_AB FROM...
    ..
    SELECT * FROM TABLE (tab_AB) ;
Run Code Online (Sandbox Code Playgroud)

当它从TABLE语句中获取SELECT时,我得到"ORA-22905:无法从非嵌套表项访问行".

是否可以在PLSQL中查询表类型?

Luk*_*ard 31

可以在PL/SQL中查询表类型,但只能查询其类型在模式级别(即PL/SQL之外)声明的嵌套表和变量.

错误

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

表示您尝试从不受支持的表类型进行查询.type_tab_AB由于该INDEX BY BINARY_INTEGER子句,您的类型是关联数组.删除INDEX BY BINARY_INTEGER子句以使您type_tab_AB的嵌套表类型.(Varrays也可以在这里工作,但我不建议使用它们,除非你知道所期望的行数的上限.当声明一个varray类型时,你需要指定最大元素数,而嵌套表类型有没有这样的限制.)

进行此更改后,您的代码可能仍然无法正常工作.您可能会遇到的下一个错误(如果不这样,请参见底部的注释)

PLS-00642:SQL语句中不允许使用本地集合类型

这是因为您选择的类型是在PL/SQL中声明的.需要声明type_tab_AB,和record_ABPL/SQL之外,使用CREATE TYPE ....

您遇到的下一个问题是因为关键字RECORD.记录类型只能在PL/SQL 中创建,不能在模式级别创建.更改RECORDOBJECT以解决此问题.

您将遇到的最后一个问题是SELECT t.AA, t.BB BULK COLLECT INTO tab_AB FROM ...声明.就目前而言,此查询将为您提供以下错误:

PL/SQL:ORA-00947:值不够

您正在从每行中选择两个项目,并且只提供一个表来批量插入数据.Oracle无法确定您是否想要将这两个项填充到您的record_AB类型中.您可以通过将查询更改为相当容易地解决此问题SELECT record_AB(t.AA, t.BB) BULK COLLECT INTO tab_AB FROM ....

总的来说,这些变化应该可以解决问题.这是一个完整的SQL*Plus脚本,它创建一个包含一些测试数据的测试表,并验证它是否可以查询表类型:

CREATE TABLE some_table (AA VARCHAR2(16 BYTE), BB VARCHAR2(16 BYTE));

INSERT INTO some_table (AA, BB) VALUES ('aa 1', 'bb 1');
INSERT INTO some_table (AA, BB) VALUES ('aaaaaaaaaa 2', 'b 2');
INSERT INTO some_table (AA, BB) VALUES ('aaaaa 3', 'bbbbbbbbbbbbbb 3');
COMMIT;

VARIABLE curs REFCURSOR;

CREATE OR REPLACE TYPE record_AB AS OBJECT
   (
      AA    VARCHAR2 (16 BYTE),
      BB    VARCHAR2 (16 BYTE)
   );
/

CREATE OR REPLACE TYPE type_tab_AB IS TABLE OF record_AB;
/

DECLARE
  tab_AB   type_tab_AB;
BEGIN
  SELECT record_AB(t.AA, t.BB)
    BULK COLLECT INTO tab_AB 
    FROM some_table t;

  OPEN :curs FOR SELECT * FROM TABLE (tab_AB) ;
END;
/

PRINT :curs
Run Code Online (Sandbox Code Playgroud)

我已经把结果SELECT荷兰国际集团的内容tab_AB到光标,并使用一个SQL*Plus游标变量,列出其内容.在所有"类型创建"和"PL/SQL过程成功完成"消息之后,我在Oracle 11g XE上运行脚本时得到的输出如下:

AA               BB
---------------- ----------------
aa 1             bb 1
aaaaaaaaaa 2     b 2
aaaaa 3          bbbbbbbbbbbbbb 3
Run Code Online (Sandbox Code Playgroud)

注意:为简单起见,我假设提问者使用的是Oracle 11或更早版本.在Oracle 12中,我相信您可以在SQL查询中使用PL/SQL中声明的类型,因此您可能不会遇到PLS-00642错误.我不能说我对Oracle 12的其他修改也可能是必要的,因为我还没有使用Oracle 12.

  • `但仅限嵌套表` 仅限嵌套表。您也可以将“table”运算符与变量数组 SQL 数据类型一起使用。 (2认同)
  • 我正在使用 oracle 12 和 11 并且刚刚遇到这个错误,将应用程序从 12 移植到 11 试图从在规范级别声明的表类型中进行选择。谢谢! (2认同)