我试图从类型表对象的变量中删除项目:
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);
我通过对象列表进行了检查,我检查了ls_attr_list.COUNT
是16,当符合条件时我尝试删除一个项目,但是我收到了这个错误:
ORA-01403:未找到数据
在此行引发:ls_attr_list.Delete(i);
FOR i IN 1..ls_attr_list.COUNT LOOP
BEGIN
IF ls_attr_list(i).attributename = 'PROTECTION_ROLE' THEN
ls_attr_list.Delete(i);
END IF;
EXCEPTION WHEN OTHERS THEN
writelog(SQLERRM,'ERROR');
END;
END LOOP;
使用输入参数初始化ls_attr_list:
PROCEDURE AttribInit(geninfo IN OUT o_geninfo,
pageinfo IN OUT o_attributepage_pageinfo,
attributelist IN OUT t_attributepage_attributelist,
enumlist IN OUT t_attributepage_enumlist)
AS
ls_attr_list := attributelist;
删除一个项目后在列表上删除时出现问题
i := attributelist.FIRST;
LOOP
IF attributelist(i).attributename = 'PROTECTION_ROLE' THEN attributelist.DELETE(i);
END IF;
EXIT WHEN i = attributelist.LAST;
i := attributelist.NEXT(i);
END LOOP;
--second FOR
FOR i in 1..attributelist.COUNT LOOP
- 当达到上一个已删除项目的索引时找不到数据
writelog(attributelist(i).attributename,'attributename');
END LOOP;
我做错了什么,有什么想法吗?
答案 0 :(得分:3)
FOR i IN 1 .. ls_attr_list.COUNT LOOP
从集合中删除元素时会导致异常/错误。每次删除一个元素时,它都会在集合中创建一个间隙,下次尝试运行该过程时,它将达到该间隙并抛出ORA-01403: no data found
。
相反,您需要在i := ls_attr_list.FIRST
和ls_attr_list.LAST
之间循环,并使用i := ls_attr_list.NEXT(i)
来获取下一个索引。
一个简化的工作示例是:
CREATE TYPE VARCHAR2_TABLE AS TABLE OF VARCHAR2(20);
/
DECLARE
vals VARCHAR2_Table := VARCHAR2_Table( 'a', 'b', 'c', 'd', 'e', 'f' );
PROCEDURE del_Val (
v IN OUT VARCHAR2_Table,
x IN VARCHAR2
)
AS
i INT;
BEGIN
IF v IS NULL OR v IS EMPTY THEN
RETURN;
END IF;
i := v.FIRST;
LOOP
IF v(i) = x THEN
DBMS_OUTPUT.PUT_LINE(i);
v.DELETE(i);
END IF;
EXIT WHEN i = v.LAST;
i := v.NEXT(i);
END LOOP;
END;
BEGIN
del_Val( vals, 'b' );
del_Val( vals, 'e' );
del_Val( vals, 'a' );
END;
/
但是使用此程序:
PROCEDURE del_Val (
v IN OUT VARCHAR2_Table,
x IN VARCHAR2
)
AS
BEGIN
FOR i IN 1 .. v.COUNT LOOP
IF v(i) = x THEN
DBMS_OUTPUT.PUT_LINE(i);
v.DELETE(i);
END IF;
END LOOP;
END;
第二次调用该过程时会导致ORA-01403: no data found
。
答案 1 :(得分:0)
我试图以一种非常清晰的方式复制场景,希望这会有所帮助。
--Obj Creation
CREATE OR REPLACE type av_obj_test
IS
object
(
col1 VARCHAR2(100),
col2 VARCHAR2(100) );
--TABLE Type creation
CREATE OR REPLACE type av_ntt_test
IS
TABLE OF av_obj_test;
--Anonymous block
DECLARE
av_t av_ntt_test:=av_ntt_test(av_obj_test('av','roy'),av_obj_test('sh','roy'));
BEGIN
FOR I IN av_t.FIRST..av_t.LAST LOOP
IF av_t(i).col1 = 'av' THEN
av_t.DELETE(I);
END IF;
END LOOP;
END;
答案 2 :(得分:0)
你没有做错任何事。当你删除某些东西时,有一个间隙导致这个错误,如@ MT0写道。 我稍微玩了你的代码,然后:
declare
t_tab T_ATTRIBUTEPAGE_ATTRIBUTELIST;
i number;
begin
t_tab:= T_ATTRIBUTEPAGE_ATTRIBUTELIST ();
t_tab.EXTEND(9);
t_tab(1):=O_ATTRIBUTEPAGE_ATTRIBUTELIST('asd',1);
t_tab(2):=O_ATTRIBUTEPAGE_ATTRIBUTELIST('tyh',2);
t_tab(3):=O_ATTRIBUTEPAGE_ATTRIBUTELIST('adgdfsd',3);
t_tab(4):=O_ATTRIBUTEPAGE_ATTRIBUTELIST('fg',4);
t_tab(5):=O_ATTRIBUTEPAGE_ATTRIBUTELIST('test',5);
t_tab(6):=O_ATTRIBUTEPAGE_ATTRIBUTELIST('test',6);
t_tab(7):=O_ATTRIBUTEPAGE_ATTRIBUTELIST('adaaaasd',7);
t_tab(8):=O_ATTRIBUTEPAGE_ATTRIBUTELIST('qwwwww',8);
t_tab(9):=O_ATTRIBUTEPAGE_ATTRIBUTELIST('poikj',9);
i:=t_tab.FIRST;
LOOP
dbms_output.put_line(t_tab(i).AttributeName||' '||t_tab(i).AttrNUMBER);
if t_tab(i).AttributeName = 'test' then t_tab.delete(i);
t_tab(i):=null;
end if;
EXIT when i=t_tab.LAST;
i:=t_tab.NEXT(i);
end loop;
dbms_output.put_line('==============================================');
for i IN t_tab.FIRST..t_tab.LAST LOOP
if t_tab(i) is null then
continue;
else
dbms_output.put_line(t_tab(i).AttributeName||' '||t_tab(i).AttrNUMBER);
end if;
end loop;
end;
/
输出:
asd 1
tyh 2
adgdfsd 3
fg 4
test 5
test 6
adaaaasd 7
qwwwww 8
poikj 9
==============================================
asd 1
tyh 2
adgdfsd 3
fg 4
adaaaasd 7
qwwwww 8
poikj 9
在t_tab.delete(i)
之后给t_tab(i):=null;
消除了间隙,并且编译器没有任何问题再次迭代这个集合并打印所有项目(因为没有间隙,有一些东西 - NULL ,和NULL是SOMETHING,希望你会明白:))。和上面提到的用户一样 - 你应该使用FIRST..LAST而不是count。
答案 3 :(得分:0)
即使集合中的最后一个元素被删除,下面的内容也将处理
DECLARE
TYPE VARCHAR2_TABLE IS TABLE OF VARCHAR2(20);
vals VARCHAR2_Table := VARCHAR2_Table( 'a', 'b', 'c', 'd', 'e', 'f' );
PROCEDURE del_Val (
v IN OUT VARCHAR2_Table,
x IN VARCHAR2
)
AS
i INT;
v_last_deleted boolean;
BEGIN
IF v IS NULL OR v IS EMPTY THEN
DBMS_OUTPUT.PUT_LINE('No more data');
RETURN;
END IF;
i := v.FIRST;
LOOP
IF v(i) = x THEN
DBMS_OUTPUT.PUT_LINE(' -> Delting element at : '||i||' that has vaulue of :'||v(i));
if (i = v.LAST) then v_last_deleted := true; end if;
v.DELETE(i);
ELSE
DBMS_OUTPUT.PUT_LINE(' --> Not Delting element at : '||i||' that has vaulue of :'||v(i));
END IF;
EXIT WHEN v IS NULL OR v IS EMPTY OR v_last_deleted OR (i = v.LAST);
i := v.NEXT(i);
END LOOP;
END;
BEGIN
DBMS_OUTPUT.PUT_LINE('Total Count : '||vals.count);
del_Val( vals, 'b' );
DBMS_OUTPUT.PUT_LINE('Total Count : '||vals.count);
del_Val( vals, 'e' );
DBMS_OUTPUT.PUT_LINE('Total Count : '||vals.count);
del_Val( vals, 'a' );
DBMS_OUTPUT.PUT_LINE('Total Count : '||vals.count);
del_Val( vals, 'a' );
DBMS_OUTPUT.PUT_LINE('Total Count : '||vals.count);
del_Val( vals, 'd' );
DBMS_OUTPUT.PUT_LINE('Total Count : '||vals.count);
del_Val( vals, 'd' );
DBMS_OUTPUT.PUT_LINE('Total Count : '||vals.count);
del_Val( vals, 'f' );
DBMS_OUTPUT.PUT_LINE('Total Count : '||vals.count);
del_Val( vals, 'd' );
DBMS_OUTPUT.PUT_LINE('Total Count : '||vals.count);
del_Val( vals, 'd' );
DBMS_OUTPUT.PUT_LINE('Total Count : '||vals.count);
del_Val( vals, 'd' );
DBMS_OUTPUT.PUT_LINE('Total Count : '||vals.count);
del_Val( vals, 'd' );
DBMS_OUTPUT.PUT_LINE('Total Count : '||vals.count);
del_Val( vals, 'c' );
DBMS_OUTPUT.PUT_LINE('Total Count : '||vals.count);
del_Val( vals, 'd' );
DBMS_OUTPUT.PUT_LINE('Total Count : '||vals.count);
del_Val( vals, 'a' );
DBMS_OUTPUT.PUT_LINE('Total Count : '||vals.count);
del_Val( vals, 'b' );
END;
/