更新这里选择,保证原子
我有一个T-SQL查询是这样的:更新这里选择,保证原子
UPDATE
[MyTable]
SET
[MyField] = @myValue
WHERE
[Id] =
(
SELECT TOP(1)
[Id]
FROM
[MyTable]
WHERE
[MyField] IS NULL
-- AND other conditions on [MyTable]
ORDER BY
[Id] ASC
)
看来,这个查询并不是原子(选择2个并发执行可以返回相同的ID两次)。
编辑: 如果我执行这个查询,SELECT返回的Id将不能用于下一次执行(因为[MyField]不会再为NULL)。但是,如果我同时执行两次这个查询,两次执行都会返回相同的ID(第二个UPDATE会覆盖第一个)。
我读过一个解决方案,以避免使用SERIALIZABLE隔离级别。那是最好/最快/最简单的方法吗?
正如我所看到的,UPDLOCK
就足够了(测试代码确认)
计算最大ID,然后在交叉连接中使用它进行更新。
WITH cte as (
SELECT TOP 1 ID
FROM [MyTable]
WHERE MYFIELD IS NULL
ORDER BY ID
)
UPDATE t
SET [ID] = cte.[ID]
FROM [MyTable] t
CROSS JOIN cte;
输出
检查编辑。使用交叉连接 –
我不相信他想更新ID列。 –
@DerrickMoeller是的,我意识到完成查询后。这就是为什么我要求样本数据和预期产出。但是这个想法就在那里。 –
这将导致顶部1值,但如果同样的,你必须返回多个值的潜力。
尝试使用DISTINCT
据我所知,顶(1)应仅返回1行,但该问题时其返回不止一行。所以我认为这可能是因为价值是一样的。所以,你可能使用类似这样
SELECT DISTINCT TOP 1 name FROM [Class];
它要么或where子句来缩小结果
TOP 1将只返回一行。 –
我以为它只是返回顶部行?那么如果这一行是相同的呢? –
如果行是一样的?我不理解你的观点,DISTINCT将返回多个值。这似乎不是他的意图。 –
你是什么意思似乎?这应该只返回一个值。除非你使用'WITH TIES'选项。 –
'select可以返回相同的ID两次'。嗯,它可能会总是返回相同的ID。 – sagi
@sagi如果更新没有被执行。 – krimog