我应该如何迭代这样的对象表?
CREATE TYPE SOME_OBJECT AS OBJECT (
ATTR1 VARCHAR2(20)
, ATTR2 VARCHAR2(30)
);
/
CREATE TYPE C_SOME_OBJECT AS TABLE OF SOME_OBJECT;
/
并且...我想将此作为过程的参数。必须在程序中初始化它吗?
PROCEDURE SOME_PROCEDURE(OBJECT IN C_SOME_OBJECT)
IS
BEGIN
--Some code here iterating IN parameter
END;
答案 0 :(得分:3)
-- NOTE #1
-- You cant use Object as name for your input variable because it is a type
-- (Types are reserved words)
PROCEDURE SOME_PROCEDURE(p_SOME_TABLE IN C_SOME_OBJECT)
IS
BEGIN
FOR i IN p_SOME_TABLE.FIRST .. p_SOME_TABLE.LAST
LOOP
-- NOTE #2 Manage it like this
-- Current iteration: p_SOME_TABLE(i)
-- Access Example : p_SOME_TABLE(i).ATTR1
-- NOTE #3 Or you can assign current iteration to a variable
-- then use that variable thought it is not by reference if you
-- do it like this.
END LOOP;
END;
<强>更新强>
另外注意不要将RECORDS与OBJECTS混淆。
OBJECT是一种SQL类型,但另一方面,RECORD是PL / SQL类型,你可以把它想象成类似于C / C ++的结构。
<强> UPDATE_2:强>
请注意,如果表为空,这不会引发任何异常,因此如果没有数据则需要处理,例如,您可以像这样使用.COUNT:
IF p_SOME_TABLE.COUNT = 0 THEN
RAISE my_exception;
END IF;
答案 1 :(得分:2)
您可以使用WHILE
循环FIRST
,NEXT
,LAST
来处理稀疏集合(元素已被删除),还需要检查未初始化集合中的元素:
PROCEDURE SOME_PROCEDURE(
I_OBJECT IN C_SOME_OBJECT
)
IS
i PLS_INTERGER;
BEGIN
-- Check that the collection is not NULL
IF I_OBJECT IS NULL THEN
RETURN;
END IF;
i := I_OBJECT.FIRST;
WHILE i IS NOT NULL LOOP
IF I_OBJECT(i) IS NOT NULL THEN
DBMS_OUTPUT.PUT_LINE( i || ' = (' I_OBJECT(i).attr1 || ', ' || I_OBJECT(i).attr2 || ')' );
ELSE
DBMS_OUTPUT.PUT_LINE( i || ' IS NULL' );
END;
END LOOP;
END;
/
然后你可以打电话给它:
DECLARE
o C_SOME_OBJECT := C_SOME_OBJECT();
BEGIN
o.EXTEND(4);
o(1) := SOME_OBJECT( '1.1', '1.2' );
-- o(2) IS NULL
o.DELETE(3); -- o(3) has been removed
o(4) := SOME_OBJECT( '4.1', '4.2' );
SOME_PROCEDURE( o );
END;
/
输出:
1 = (1.1, 1.2)
2 IS NULL
4 = (4.1, 4.2)
FOR ... LOOP
的问题:
使用FOR i IN 1 .. o.COUNT LOOP
:
DECLARE
o C_SOME_OBJECT := C_SOME_OBJECT(
SOME_OBJECT( '1.1', '1.2' ),
SOME_OBJECT( '2.1', '2.2' ),
SOME_OBJECT( '3.1', '3.2' ),
SOME_OBJECT( '4.1', '4.2' )
);
BEGIN
o.DELETE(1);
FOR i IN 1 .. o.COUNT LOOP
IF I_OBJECT(i) IS NOT NULL THEN
DBMS_OUTPUT.PUT_LINE( i || ' = (' I_OBJECT(i).attr1 || ', ' || I_OBJECT(i).attr2 || ')' );
ELSE
DBMS_OUTPUT.PUT_LINE( i || ' IS NULL' );
END;
END LOOP;
END;
/
输出:
1 IS NULL
2 = (2.1, 2.2)
3 = (3.1, 3.2)
这输出元素1,它不存在,并且不输出确实存在的元素4.
使用FOR i IN o.FIRST .. o.LAST LOOP
:
DECLARE
o C_SOME_OBJECT := C_SOME_OBJECT(
SOME_OBJECT( '1.1', '1.2' ),
SOME_OBJECT( '2.1', '2.2' ),
SOME_OBJECT( '3.1', '3.2' ),
SOME_OBJECT( '4.1', '4.2' )
);
BEGIN
o.DELETE(2);
FOR i IN o.FIRST .. o.LAST LOOP
IF I_OBJECT(i) IS NOT NULL THEN
DBMS_OUTPUT.PUT_LINE( i || ' = (' I_OBJECT(i).attr1 || ', ' || I_OBJECT(i).attr2 || ')' );
ELSE
DBMS_OUTPUT.PUT_LINE( i || ' IS NULL' );
END;
END LOOP;
END;
/
输出:
1 = (1.1, 1.2)
2 IS NULL
3 = (3.1, 3.2)
4 = (4.1, 4.2)
当o.COUNT
仅为3时,这会输出4个元素(包括删除的第2个元素)。