问题描述
我正在处理Oracle中的嵌套表和VArray(为澄清起见,这是在大学学习的目的)。我有这个TABLE结构,将数据放入后一切正常。
CREATE OR REPLACE TYPE Addendum AS OBJECT (
idCode VARCHAR2(10),signature_date TIMESTAMP,--A VARRAY(5) OF REF STUDENT (STUDENT IF THE TYPE,TSTUDENT THE TABLE)
studentlist student_list,--A TABLE OF REF STAFF (STAFF IS THE TYPE,TSTAFF THE TABLE)
staff_members tStaff,pdi_manager REF PDI
) FINAL;
CREATE TABLE Addendums OF Addendum
nesTED TABLE staff_members STORE AS staffmembers_nt;
CREATE UNIQUE INDEX ADDENDUMS_IDCODE_UINDEX on ADDENDUMS (IDCODE);
CREATE OR REPLACE TYPE tAddendum AS TABLE OF Addendum;
在第一次尝试中,我执行了一个类似SELECT * FROM ADDENDUMS
的查询,它向我展示了这件事:
0000000000,2019-09-01 00:00:00.000000,"{<Failed to load> oracle.sql.REF,<Failed to load> oracle.sql.REF,<Failed to load> oracle.sql.REF}",<Failed to load> oracle.sql.REF}"
0000000001,<Failed to load> oracle.sql.REF}"
我还尝试使用DEREF指令进行选择,并使用select ad.IDCODE,ad.SIGNATURE_DATE,DEREF(ad.STUDENTLIST),DEREF(ad.STAFF_MEMBERS),DEREF(ad.PDI_RESPONSABLE) from UOC.ADDENDUMS ad;
显式引用这些列,它只显示正确取消引用的PDI_MANAGER。
如何使用VARRAY和nesTED TABLE?例如, sql 的正确语法是什么(不是this question中的PL / sql)?
解决方法
您可以使用表集合表达式CROSS JOIN
VARRAY
(或嵌套表),然后DEREF(VALUE(collection_alias)).column_name
来获取值。
例如:
SELECT a.idcode,a.signature_date,DEREF(VALUE(s)).id AS id,DEREF(VALUE(s)).name AS name
FROM ADDENDUMS a
CROSS JOIN TABLE( a.studentlist ) s;
针对您的类型,
CREATE TYPE Student AS OBJECT(
id NUMBER,name VARCHAR2(50)
);
CREATE TABLE students OF Student (
CONSTRAINT students__id__pk PRIMARY KEY ( id )
);
CREATE TYPE student_list AS VARRAY(5) OF REF Student;
CREATE OR REPLACE TYPE Addendum AS OBJECT (
idCode VARCHAR2(10),signature_date TIMESTAMP,--A VARRAY(5) OF REF STUDENT (STUDENT IF THE TYPE,TSTUDENT THE TABLE)
studentlist student_list
) FINAL;
CREATE TABLE Addendums OF Addendum;
和一些示例数据:
BEGIN
INSERT INTO Students ( id,name ) VALUES ( 1,'AAA' );
INSERT INTO Students ( id,name ) VALUES ( 2,'BBB' );
INSERT INTO Students ( id,name ) VALUES ( 3,'CCC' );
INSERT INTO Students ( id,name ) VALUES ( 4,'DDD' );
INSERT INTO Students ( id,name ) VALUES ( 5,'EEE' );
INSERT INTO Students ( id,name ) VALUES ( 6,'FFF' );
INSERT INTO Addendums ( idCode,signature_date,studentlist )
VALUES (
1,SYSTIMESTAMP,student_list(
( SELECT REF(s) FROM students s WHERE id = 2 ),( SELECT REF(s) FROM students s WHERE id = 4 ),( SELECT REF(s) FROM students s WHERE id = 1 )
)
);
END;
/
输出:
IDCODE | SIGNATURE_DATE | ID | NAME :----- | :--------------------------- | -: | :--- 1 | 01-OCT-20 05.01.00.699863 PM | 2 | BBB 1 | 01-OCT-20 05.01.00.699863 PM | 4 | DDD 1 | 01-OCT-20 05.01.00.699863 PM | 1 | AAA
db 提琴here
(注意:没有提供类型TStaff
的示例代码,因此我将其删除;但是该方法与VARRAY
相同。)
在更高的Oracle版本中(支持OFFSET m ROWS FETCH NEXT n ROWS
语法),您可以使用嵌套查询从VARRAY
获取值。但是,Oracle 11g不支持此功能:
SELECT a.idcode,( SELECT DEREF(VALUE(t)).name
FROM TABLE( a.studentlist ) t
OFFSET 0 ROWS FETCH NEXT 1 ROW ONLY ) AS name1,( SELECT DEREF(VALUE(t)).name
FROM TABLE( a.studentlist ) t
OFFSET 1 ROWS FETCH NEXT 1 ROW ONLY ) AS name2,( SELECT DEREF(VALUE(t)).name
FROM TABLE( a.studentlist ) t
OFFSET 2 ROWS FETCH NEXT 1 ROW ONLY ) AS name3,( SELECT DEREF(VALUE(t)).name
FROM TABLE( a.studentlist ) t
OFFSET 3 ROWS FETCH NEXT 1 ROW ONLY ) AS name4,( SELECT DEREF(VALUE(t)).name
FROM TABLE( a.studentlist ) t
OFFSET 4 ROWS FETCH NEXT 1 ROW ONLY ) AS name5
FROM ADDENDUMS a;
输出:
IDCODE | SIGNATURE_DATE | NAME1 | NAME2 | NAME3 | NAME4 | NAME5 :----- | :------------------------ | :---- | :---- | :---- | :---- | :---- 1 | 01-OCT-20 17.09.08.790538 | BBB | DDD | AAA | null | null
db 提琴here