在 PL/SQL 块中定义引用自身集合的记录类型

Define a record type in PL/SQL block that references a collection of itself

如何在包含 属性 的 PL/SQL 匿名块中定义一个记录类型,该 属性 是其自身的集合?看下面的例子:

DECLARE
    type t_item is record (
        name varchar2(64),
        children t_items              -- referencing t_items type
    );
    type t_items is table of t_item;  -- referencing t_item type

BEGIN
    -- script code
END

PL/SQL 没有类型提升,因此 Oracle 引擎引发异常:

PLS-00498: illegal use of a type before its declaration

如何定义在 属性 children 中包含 table of t_item 的记录 t_item

您可以通过继承使用 SQL 范围内定义的对象:

SQL Fiddle

Oracle 11g R2 架构设置:

CREATE TYPE abstract_item IS OBJECT (
  name VARCHAR2(64)
) NOT FINAL NOT INSTANTIABLE
/

CREATE TYPE t_items IS TABLE OF abstract_item
/

CREATE TYPE t_item UNDER abstract_item (
  children t_items
) INSTANTIABLE
/

查询 1:

SELECT t_item(
         '1',
         t_items(
           t_item( '1.1', t_items() ),
           t_item(
             '1.2',
             t_items(
               t_item( '1.2.1', null )
             )
           ),
           t_item( '1.3', null )
         )
       )
FROM   DUAL

Results:(SQLFiddle 不能很好地显示它 - 但它运行没有错误)

| T_ITEM('1',T_ITEMS(T_ITEM('1.1',T_ITEMS()),T_ITEM('1.2',T_ITEMS(T_ITEM('1.2.1',NULL))),T_ITEM('1.3',NULL))) |
|-------------------------------------------------------------------------------------------------------------|
|                                                                                  oracle.sql.STRUCT@2a094aab |

您可以在 PL/SQL 中使用类似的声明:

DECLARE
  items t_item;
BEGIN
  items = t_item( 'Item Name', t_items( /* ... */ ) );
END;
/

参考对象的示例:

create or replace type item; -- forward declaration 
/
create or replace type l_item_ref is table of ref item;
/
create or replace type item  is object( a number, list l_item_ref)
/
CREATE TABLE t_item OF item nested table list store as ref_items
/
declare 

  v_list l_item_ref;

begin 

insert into t_item values(1,null);
insert into t_item values(2,null);
insert into t_item values(3,null);
select ref(p) bulk collect into v_list  from t_item p;

insert into t_item values(123,v_list);
 commit;
end;

select p.a,p.list from t_item p;

下面是创建自定义记录类型然后使用自定义记录类型创建 table 类型的示例。

在您的规范文件中,您可以定义自定义类型,如下所示。

TYPE STUDENT IS RECORD
    ("ID" NUMBER, 
     "NAME" VARCHAR2(100)
    );
TYPE STUDENT_TABLE IS TABLE OF STUDENT;

现在在您的包体中,您可以使用您定义如下的自定义 table。

students STUDENT_TABLE; (Declaration of variable of type student_table)

因为这不能用作 table 你不能直接插入它。还有一件事要记住,如 table 如果您一个接一个地插入记录,它基本上会创建一个新条目,但在自定义记录类型的情况下,将替换旧的记录类型。

**SELECT
      123 AS ID,
      abc AS NAME
      BULK COLLECT INTO STUDENT_TABLE FROM DUAL;** --(This is how we insert)

考虑一下,如果我们再次执行具有不同值的相同语句,它将覆盖前一个语句,如上所述。

因此,如果您有追加记录的要求,那么您可以按照以下方法进行操作。

students STUDENT_TABLE;
studentsTemp STUDENT_TABLE; (Declare a temp also to store the previous value)

**SELECT
      123 AS ID,
      abc AS NAME
      BULK COLLECT INTO STUDENT_TABLE FROM DUAL;
studentsTemp := STUDENT_TABLE;

SELECT
    789 AS ID,
    xyz AS NAME
    BULK COLLECT INTO STUDENT_TABLE FROM DUAL;
studentsTemp := students multiset union all studentsTemp;** --(This is how you can append)

下面是通过游标return的方法。

OPEN CursorStudent FOR
    SELECT ID,
           NAME,
      FROM TABLE(studentsTemp); (Will return all records.)

使用它的好处是您可以避免临时 tables 和更少的脚本在移动到更高的环境时维护。