【问题标题】:Oracle: How to DEREF a VARRAY of REFs and NESTED TABLE of REFs?Oracle:如何 DEREF VARRAY 的 REF 和嵌套的 REF 表?
【发布时间】:2020-10-01 12:59:47
【问题描述】:

我正在处理 Oracle 中的嵌套表和 VArray(澄清一下,这是为了在大学学习)。我有这个TABLE结构,我把数据放进去就一切OK了。

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}"

我还尝试使用 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)?

【问题讨论】:

    标签: oracle oracle11g user-defined-types


    【解决方案1】:

    您可以使用表集合表达式CROSS JOINVARRAY(或嵌套表)然后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;
    /
    

    输出:

    识别码 | SIGNATURE_DATE |身份证 |姓名 :----- | :---------------------------- | -: | :--- 1 | 01-OCT-20 05.01.00.699863 下午 | 2 | BBB 1 | 01-OCT-20 05.01.00.699863 下午 | 4 | DDD 1 | 01-OCT-20 05.01.00.699863 下午 | 1 | AAA

    db小提琴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;
    

    输出:

    识别码 | SIGNATURE_DATE |姓名1 |名称2 |姓名3 |姓名4 |名称5 :----- | :------------------------ | :---- | :---- | :---- | :---- | :---- 1 | 01-OCT-20 17.09.08.790538 |血脑屏障 | DDD | AAA | |

    db小提琴here

    【讨论】:

    • 完美!这是我预期和需要的工作。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 2021-02-20
    • 1970-01-01
    • 1970-01-01
    • 2015-06-29
    • 2018-11-01
    • 1970-01-01
    • 2018-09-15
    • 1970-01-01
    相关资源
    最近更新 更多