For loop PL/SQL在for循环内部执行即时异常处理
在下面的PL/SQL代码中,表1包含表名tname、列名cname和rowid rid。For循环从表_ONE中获取记录,并更新表tname中的列cname,以获取行id为rid的记录。但是,如果要在tname中更新的记录被锁定,则for循环将被卡住,并且不会处理来自表1的更多记录。理想情况下,脚本将忽略更新失败的记录并继续。请告知可能出现的问题For loop PL/SQL在for循环内部执行即时异常处理,for-loop,plsql,record,locked,execute-immediate,For Loop,Plsql,Record,Locked,Execute Immediate,在下面的PL/SQL代码中,表1包含表名tname、列名cname和rowid rid。For循环从表_ONE中获取记录,并更新表tname中的列cname,以获取行id为rid的记录。但是,如果要在tname中更新的记录被锁定,则for循环将被卡住,并且不会处理来自表1的更多记录。理想情况下,脚本将忽略更新失败的记录并继续。请告知可能出现的问题 BEGIN FOR c IN (SELECT * FROM TABLE_ONE a ) LOOP DECLARE
BEGIN
FOR c IN (SELECT * FROM TABLE_ONE a )
LOOP
DECLARE
TNAME varchar2(30);
CNAME varchar2(30);
RID ROWID;
X number;
updt_stmt varchar2(300);
BEGIN
BEGIN
TNAME := c.TNAME;
CNAME := c.CNAME;
RID := c.RID;
DBMS_OUTPUT.PUT_LINE( TNAME || '=>' || CNAME);
updt_stmt := 'UPDATE ' || TNAME || ' SET ' || CNAME || ' = ''123'' WHERE ROWID like ''%' || RID || '%''';
EXECUTE IMMEDIATE updt_stmt;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('ERROR');
END;
END;
END LOOP;
END;
未测试,但我认为您可以首先尝试使用锁定记录以进行更新,并在其他事务处于活动状态时指定NOWAIT以导致失败。然后可以捕获此异常并跳过处理。以下是一个未经测试的示例:
DECLARE
x ROWID;
resource_busy EXCEPTION;
PRAGMA EXCEPTION_INIT(resource_busy,
-00054);
BEGIN
FOR c IN (SELECT *
FROM table_one a)
LOOP
DECLARE
tname VARCHAR2(30);
cname VARCHAR2(30);
rid ROWID;
x NUMBER;
updt_stmt VARCHAR2(300);
BEGIN
BEGIN
tname := c.tname;
cname := c.cname;
rid := c.rid;
dbms_output.put_line(tname || '=>' || cname);
BEGIN
EXECUTE IMMEDIATE 'SELECT rowid FROM ' || tname ||
' WHERE rowid = :x FOR UPDATE NOWAIT'
INTO x
USING rid;
EXCEPTION
WHEN resource_busy THEN
dbms_output.put_line('Record locked; try again later.');
CONTINUE;
END;
updt_stmt := 'UPDATE ' || tname || ' SET ' || cname ||
' = ''123'' WHERE ROWID like ''%' || rid || '%''';
EXECUTE IMMEDIATE updt_stmt;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('ERROR');
END;
END;
END LOOP;
END;