Oracle:如何取消对REF的VARRAY和嵌套的REF TABLE的引用?

问题描述

我正在处理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

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...