PL / SQL - 不更新已更改的行

时间:2015-11-06 05:38:17

标签: oracle plsql transactions

我计划在我庞大的桌子上进行长时间更新(超过十亿行)。此更新会将一列的值乘以固定数字。

问题在于,在我的更新期间(可能持续几个小时)肯定会有更新某些行的短事务,并且这些行将具有不应更新的正确值,尽管它们仍将满足我的更新'条件。

所以问题是 - 如何跳过(不更新)在我长时间运行的更新事务之外更新的行?

3 个答案:

答案 0 :(得分:4)

一种方法是使用 FOR UPDATE SKIP LOCKED ,以便其他会话无法选择已经选择进行更新的行。

例如,

第1节:

SQL> SELECT empno, deptno
  2    FROM emp  WHERE
  3   deptno = 10
  4  FOR UPDATE NOWAIT;

     EMPNO     DEPTNO
---------- ----------
      7782         10
      7839         10
      7934         10

SQL>

第2节:

SQL> SELECT empno, deptno
  2    FROM emp  WHERE
  3   deptno in (10, 20)
  4  FOR UPDATE NOWAIT;
  FROM emp  WHERE
       *
ERROR at line 2:
ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired

现在让我们跳过会话1锁定的行

SQL> SELECT empno, deptno
  2    FROM emp  WHERE
  3   deptno IN (10, 20)
  4  FOR UPDATE SKIP LOCKED;

     EMPNO     DEPTNO
---------- ----------
      7369         20
      7566         20
      7788         20
      7876         20
      7902         20

SQL>

因此,部门= 10被会话1锁定,然后部门= 20被会话2锁定。

答案 1 :(得分:1)

我做过类似你的问题,但我的表格并不像你的那么大。

我重新设计了我的表,添加了2列。

created_date:插入数据时触发器输入sysdate。

modified_date:触发器在更新数据时放入sysdate。

然后我可以在where子句中使用created_date或modified_date。

示例:

UPDATE TABLE table_name
SET column_name = 'values'
WHERE created_date < SYSDATE;

我希望这会对你有所帮助。

答案 2 :(得分:0)

哦,我完全忘记了这个问题。 因此,我最终通过将副本保存到另一个表来创建当前行的快照(我只需要更新那些满足给定条件的行)。之后,我更新了尚未更改其值的行(使用合并)。