可以在 PL/SQL 中查询表类型,但只能查询其类型在模式级别(即在 PL/SQL 之外)声明的嵌套表和可变数组。
错误
ORA-22905: 无法访问非嵌套表项中的行
表示您正在尝试从不受支持的表类型进行查询。由于子句,您的类型type_tab_AB
是关联数组。INDEX BY BINARY_INTEGER
删除该INDEX BY BINARY_INTEGER
子句以使您type_tab_AB
成为嵌套表类型。(可变数组也可以在这里工作,但我不建议使用它们,除非您知道预期行数的上限。声明可变数组类型时,您需要指定最大元素数,而嵌套表类型有没有这样的限制。)
进行此更改后,您的代码可能仍然无法正常工作。您可能会遇到的下一个错误(如果没有,请参阅底部的注释)是
PLS-00642:SQL 语句中不允许本地集合类型
这是因为您选择的类型是在 PL/SQL 中声明的。您需要在 PL/SQLtype_tab_AB
之外record_AB
使用CREATE TYPE ...
.
您遇到的下一个问题将是由于关键字RECORD
。记录类型只能在 PL/SQL 内部创建,它们不能在模式级别创建。更改RECORD
为OBJECT
解决此问题。
您将遇到的最后一个问题是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
我已将SELECT
ing 的内容的结果tab_AB
放入游标中,并使用 SQL*Plus 游标变量列出其内容。当我在 Oracle 11g XE 上运行脚本时,在所有“创建类型”和“PL/SQL 过程成功完成”消息之后,我得到的输出如下:
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。