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) ;
当从TABLE语句获取SELECT时,我得到“ORA-22905:无法从非嵌套表项访问行”.
解决方法
ORA-22905: cannot access rows from a non-nested table item
表示您尝试从不受支持的表类型进行查询.您的类型type_tab_AB是一个关联数组,因为INDEX BY BINARY_INTEGER子句.删除INDEX BY BINARY_INTEGER子句以使type_tab_AB成为嵌套表类型. (Varrays也可以在这里工作,但我不建议使用它们,除非你知道所期望的行数的上限.当声明一个varray类型时,你需要指定最大元素数,而嵌套表类型有没有这样的限制.)
进行此更改后,您的代码可能仍然无法正常工作.您可能会遇到的下一个错误(如果不这样,请参见底部的注释)
PLS-00642: local collection types not allowed in sql statements
这是因为您选择的类型是在PL / sql中声明的.您需要使用CREATE TYPE …在PL / sql之外声明type_tab_AB和record_AB.
您遇到的下一个问题是由于关键字RECORD.记录类型只能在PL / sql,they cannot be created at schema level中创建.将RECORD更改为OBJECT以解决此问题.
您将遇到的最后一个问题是使用SELECT t.AA,t.BB BULK COLLECT INTO tab_AB FROM …语句.就目前而言,此查询将为您提供以下错误:
PL/sql: ORA-00947: not enough values
您正在从每行中选择两个项目,并且只提供一个表来批量插入数据. 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
我将选择tab_AB的内容的结果放入游标,并使用sql * Plus游标变量列出其内容.在所有“类型创建”和“PL / sql过程成功完成”消息之后,我在Oracle 11g XE上运行脚本时得到的输出如下:
AA BB ---------------- ---------------- aa 1 bb 1 aaaaaaaaaa 2 b 2 aaaaa 3 bbbbbbbbbbbbbb 3
注意:为简单起见,我假设提问者使用的是Oracle 11或更早版本.在Oracle 12中,我相信您可以在SQL查询中使用PL / sql中声明的类型,因此您可能不会遇到PLS-00642错误.我不能说我对Oracle 12的其他修改也可能是必要的,因为我还没有使用Oracle 12.