我们有一个用于更新特定列的脚本。在这个脚本中,我们使用了一个FOR UPDATE
游标。在脚本的第一个版本中,我们没有使用FOR UPDATE
子句的OF
部分。正如我们发现here和here这不应该影响脚本,因为所有连接表的所有行都应该被锁定,因此可以更新。Oracle FOR UPDATE(OF)游标行为
但是,当我们在运行脚本时虽然打印了日志消息,但未对列(column_a)进行更新。
当我们在光标有FOR UPDATE OF t1.column_a
的情况下更改脚本时,会出现相同的日志消息,但更新是正确的!
任何人都可以解释为什么没有OF
子句的脚本不起作用吗?
Oracle数据库版本为'Oracle Database 11g企业版版本11.2.0.3.0',也使用'Oracle Database 12c企业版版本12.1.0.2.0 - 64位'进行了测试。
这里是执行脚本的一个简单的版本:
BEGIN
-- anonymous procedure
DECLARE PROCEDURE update_column_a IS
c_to_find CONSTANT NUMBER := -42;
c_constant_value CONSTANT VARCHAR2 := 'value';
CURSOR c_my_cursor IS
SELECT t1.*
FROM table_1 t1, table_2 t2, table_3 t3
WHERE t1.t2_id = t2.id
AND t2.t3_id = t3.id
AND t3.column_b = c_to_find
-- FOR UPDATE with OF clause works
-- FOR UPDATE OF t1.column_a;
-- FOR UPDATE without OF clause does not
FOR UPDATE;
BEGIN
FOR cursor_rec IN c_my_cursor LOOP
IF cursor_rec.column_a IS NULL OR cursor_rec.column_a = '' THEN
dbms_output.put_line('Updating column...');
UPDATE t1 SET column_a = c_constant_value WHERE CURRENT OF c_my_cursor;
ELSE
dbms_output.put_line('Column already set...');
END IF;
END LOOP;
END update_column_a;
-- anonymous execution
BEGIN
update_column_a;
END;
END;
/
正如我所了解的文档,这减少了对具有指定列的表的锁定。根据该[网站](http://www.fast-track.cc/___aaa_pl_sql_cursor_for_update.htm)应该锁定所有行。 '如果游标将连接表,则两个表中游标返回的所有行都被锁定。' – sebastian
我们没有得到任何异常。这也让我们感到困惑,因为它不会更新列。 – sebastian
我不会相信任何Don Burleson通常会发布的东西,但他似乎就在那里! –