Oracle:如何 DEREF A VARRAY of REFs 和 NESTED TABLE of REFs?
Oracle: How to DEREF a VARRAY of REFs and NESTED TABLE of REFs?
我正在处理 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,<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,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,<failed to load> oracle.sql.REF}","{<failed to load> oracle.sql.REF,<failed to load> oracle.sql.REF,<failed to load> oracle.sql.REF}"
我还尝试 select 使用 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)?
您可以使用 table 集合表达式 CROSS JOIN
VARRAY
(或嵌套 table),然后 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<>fiddle here
(注意:没有为类型 TStaff
提供示例代码,所以我删除了那部分;但是方法与 VARRAY
相同。 )
在以后的 Oracle 版本(支持 OFFSET m ROWS FETCH NEXT n ROWS
语法)中,您可以使用嵌套查询从 VARRAY
中获取值;然而,这在 Oracle 11g 中不受支持:
SELECT a.idcode,
a.signature_date,
( 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<>fiddle here
我正在处理 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,<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,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,<failed to load> oracle.sql.REF}","{<failed to load> oracle.sql.REF,<failed to load> oracle.sql.REF,<failed to load> oracle.sql.REF}"
我还尝试 select 使用 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)?
您可以使用 table 集合表达式 CROSS JOIN
VARRAY
(或嵌套 table),然后 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<>fiddle here
(注意:没有为类型 TStaff
提供示例代码,所以我删除了那部分;但是方法与 VARRAY
相同。 )
在以后的 Oracle 版本(支持 OFFSET m ROWS FETCH NEXT n ROWS
语法)中,您可以使用嵌套查询从 VARRAY
中获取值;然而,这在 Oracle 11g 中不受支持:
SELECT a.idcode,
a.signature_date,
( 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<>fiddle here