SQL(mySQL)更新select处理的所有记录中的某些值

时间:2010-01-21 10:28:05

标签: mysql select

我在他们的C API中使用mySQL,但这不应该是相关的。 我的代码必须处理符合某些条件的表中的记录,然后更新所述记录以将其标记为已处理。表中的行由另一个我无法控制的进程修改/插入/删除。我担心在下面,UPDATE可能会错误地标记一些记录,因为匹配的记录集可能在步骤1和步骤3之间发生了变化。

SELECT * FROM myTable WHERE <CONDITION>; # step 1
<iterate over the selected set of lines. This may take some time.> # step 2
UPDATE myTable SET processed=1 WHERE <CONDITION> # step 3

确保UPDATE更新所有已处理的线路的智能方法是什么,只有它们?事务似乎不适合该法案,因为它不提供那种隔离:最近修改的记录不在最初选择的集合中,可能仍然是UPDATE语句的目标。出于同样的原因,SELECT ... FOR UPDATE似乎没有帮助,虽然听起来很有希望: - )

我能看到的唯一方法是使用临时表来记忆要处理的行集,执行以下操作:

CREATE TEMPORARY TABLE workOrder (jobId INT(11));
INSERT INTO workOrder SELECT myID as jobId FROM myTable WHERE <CONDITION>;
SELECT * FROM myTable WHERE myID IN (SELECT * FROM workOrder);
<iterate over the selected set of lines. This may take some time.>
UPDATE myTable SET processed=1 WHERE myID IN (SELECT * FROM workOrder);
DROP TABLE workOrder;

但这似乎很浪费而且效率不高。

有什么更聪明的吗?

非常感谢SQL新手。

2 个答案:

答案 0 :(得分:1)

有几种选择:

  1. 您可以锁定表格

  2. 您可以添加AND foo_id IN(all_the_ids_you_processed)作为更新条件。

  3. 您可以在选择之前更新,然后只选择更新的行(即按处理日期)

答案 1 :(得分:1)

我最终通过在该表中使用根据其状态标记行的列来解决此问题。这一栏让我实现了一个简单的状态机。从概念上讲,我对此状态有两个可能的值:

kNoProcessingPlanned = 0; #default "idle" value
kProcessingUnderWay = 1;

现在我的算法做了这样的事情:

UPDATE myTable SET status=kProcessingUnderWay WHERE <CONDITION>; # step 0

SELECT * FROM myTable WHERE status=kProcessingUnderWay; # step 1
    <iterate over the selected set of lines. This may take some time.> # step 2
UPDATE myTable SET processed=1, status=kNoProcessingPlanned WHERE status=kProcessingUnderWay # step 3

这种在几种状态下拥有行的想法可以根据需要扩展到多个状态。

相关问题