如何在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:在声明类型之前非法使用该类型
如何定义在其属性t_item
中包含table of t_item
的记录children
?
答案 0 :(得分:3)
您可以使用通过继承在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;
/
答案 1 :(得分:2)
有关对象的示例:
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;
答案 2 :(得分:0)
下面是创建自定义记录类型,然后使用自定义记录类型创建表类型的示例。
在您的规格文件中,您可以按以下定义自定义类型。
TYPE STUDENT IS RECORD
("ID" NUMBER,
"NAME" VARCHAR2(100)
);
TYPE STUDENT_TABLE IS TABLE OF STUDENT;
现在,在包主体中,您可以使用如下定义的自定义表。
students STUDENT_TABLE; (Declaration of variable of type student_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)
下面是通过游标返回它的方法。
OPEN CursorStudent FOR
SELECT ID,
NAME,
FROM TABLE(studentsTemp); (Will return all records.)
使用此功能的优点是,当移至更高的环境时,可以避免使用临时表并减少要维护的脚本。