在 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 范围内定义的对象:
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 和更少的脚本在移动到更高的环境时维护。
如何在包含 属性 的 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 范围内定义的对象:
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 和更少的脚本在移动到更高的环境时维护。