将T_ATTRIBUTEPAGE_ATTRIBUTELIST
作为这样的目标表:
CREATE OR REPLACE TYPE "T_ATTRIBUTEPAGE_ATTRIBUTELIST" IS TABLE OF o_ATTRIBUTEPAGE_ATTRIBUTELIST;
CREATE OR REPLACE TYPE "O_ATTRIBUTEPAGE_ATTRIBUTELIST" IS OBJECT (
WizAttrEditID NUMBER,
InternalIndex NUMBER,
DimensionObjectID NUMBER,
AttributeName VARCHAR2(50),
AttributeLabel VARCHAR2(50),
AttributeType NUMBER,
AttributeLength VARCHAR2(50),
MandatoryAttribute NUMBER,
ReadOnly NUMBER,
Name VARCHAR2(2000),
Num NUMBER,
IsModified NUMBER,
Colour NUMBER);
attributelist t_attributepage_attributelist;
我正在删除表格中的一项:
attributelist.DELETE(ln_attrib_pos_function);
然后,如果我尝试遍历列表,我有
未找到数据
FOR i in 1..attributelist.COUNT LOOP
...
END LOOP;
我也尝试使用FIRST
和LAST
方法,但结果是一样的。
我想要的是以某种方式再次使表密集,以便删除后的后续迭代可以没有任何错误。我尝试使用EXISTS
方法创建新表并消除与初始表的差距,但我得到了
超出计数的订阅
我认为这是因为循环跳过了已删除的项目,因此i索引转向 如果删除的项目位于索引11,则从10到12
FOR i in 1..attributelist.COUNT LOOP
IF attributelist.EXISTS(i) THEN
ls_attribute_list.EXTEND;
ls_attribute_list(i) := attributelist(i);
ELSE
CONTINUE;
END IF;
END LOOP;
attributelist := ls_attribute_list;
基本上我希望在删除一个或多个项目后,初始attributelist
可以进行迭代。
答案 0 :(得分:2)
这应该有效
FOR i in attributelist.first..attributelist.last LOOP
如果您在中间删除COUNT
减少。 <{1}}和FIRST
以及LAST
就是您所需要的。
编辑:但是为了避免循环删除的条目,您可以按照MT0的建议进行操作并使用EXISTS
。
NEXT
使用以下例程测试它:
i := attributelist.first;
LOOP
dbms_output.put_line(attributelist(i).WizAttrEditID);
exit when i = attributelist.last;
i := attributelist.next(i);
END LOOP;
输出:
set serveroutput on
declare
attributelist t_attributepage_attributelist;
ls_attribute_list t_attributepage_attributelist;
i number;
begin
attributelist := t_attributepage_attributelist();
ls_attribute_list := t_attributepage_attributelist();
attributelist.extend;
attributelist(1) := O_ATTRIBUTEPAGE_ATTRIBUTELIST(1,null,null,null,null,null,null,null,null,null,null,null,null);
attributelist.extend;
attributelist(2) := O_ATTRIBUTEPAGE_ATTRIBUTELIST(2,null,null,null,null,null,null,null,null,null,null,null,null);
attributelist.extend;
attributelist(3) := O_ATTRIBUTEPAGE_ATTRIBUTELIST(3,null,null,null,null,null,null,null,null,null,null,null,null);
attributelist.extend;
attributelist(4) := O_ATTRIBUTEPAGE_ATTRIBUTELIST(4,null,null,null,null,null,null,null,null,null,null,null,null);
attributelist.delete(1);
attributelist.delete(3);
dbms_output.put_line('count='||attributelist.count||' last='||attributelist.last);
i := attributelist.first;
LOOP
exit when i is null; -- in case everything is deleted
dbms_output.put_line(attributelist(i).WizAttrEditID);
exit when i = attributelist.last;
i := attributelist.next(i);
END LOOP;
end;
答案 1 :(得分:1)
最好的解决方案是接受如果您要从集合中删除它们,那么它们可以是稀疏的并使用FIRST/LAST/NEXT
方法迭代它们:
i := attributeList.FIRST;
LOOP
-- do stuff
EXIT WHEN i = attributeList.LAST;
i := attributeList.NEXT(i);
END LOOP;
是的,输入比FOR i IN attributeList.FIRST .. attributeList.LAST LOOP ... do stuff ... END LOOP;
稍微多一些但不是很多,当您忘记处理几个程序之前的删除时,您的应用程序逻辑不会突然在随机位置开始破坏。
但是,如果要创建稀疏集合的非稀疏副本,则可以执行以下操作:
CREATE FUNCTION compactCollection(
list IN T_ATTRIBUTEPAGE_ATTRIBUTELIST,
) RETURN T_ATTRIBUTEPAGE_ATTRIBUTELIST DETERMINISTIC
IS
BEGIN
IF list IS NULL THEN
RETURN NULL;
END IF;
RETURN T_ATTRIBUTEPAGE_ATTRIBUTELIST()
MULTISET UNION list;
END;
/
但最好只使用适当的迭代方法进行稀疏集合。
<强>更新强>
MULTISET UNION
运算符将连接两个集合,返回一个新集合(与操作数类型相同)。连接的副作用是产生的集合是密集的。
因此,将空集合与稀疏集合连接将导致稀疏集合的压缩(密集)版本。
attributeList := T_ATTRIBUTEPAGE_ATTRIBUTELIST() MULTISET UNION attributeList;
将给出相同的元素(以相同的顺序),但只是压缩元素索引。
(如果您希望使用FIRST/LAST/NEXT
次迭代的较长版本的代码,请参阅first edit of this answer)
答案 2 :(得分:0)
我设法做的似乎工作是使用一个辅助的对象表,我用删除的项目迭代原始数组,然后删除一些辅助列表中的间隙,然后将此列表返回给原始数组,如下所示:
FOR i in 1..attributelist.COUNT+1 LOOP
IF attributelist.EXISTS(i) THEN
j := j+1;
ls_attribute_list.EXTEND;
ls_attribute_list(j) := attributelist(i);
END IF;
END LOOP;
attributelist := ls_attribute_list;