当前位置:  开发笔记 > 编程语言 > 正文

有没有办法同时SELECT和UPDATE行?

如何解决《有没有办法同时SELECT和UPDATE行?》经验,为你挑选了5个好方法。

我想基于一个简单的标准更新一组行,并获取已更改的PK列表.我以为我可以做这样的事情,但我担心可能的并发问题:

SELECT Id FROM Table1 WHERE AlertDate IS NULL;
UPDATE Table1 SET AlertDate = getutcdate() WHERE AlertDate IS NULL;

如果包含在事务中,是否存在可能发生的并发问题?或者有更好的方法吗?



1> Mark Canlas..:

考虑查看OUTPUT子句:

USE AdventureWorks2012;  
GO  

DECLARE @MyTableVar table(  
    EmpID int NOT NULL,  
    OldVacationHours int,  
    NewVacationHours int,  
    ModifiedDate datetime);  

UPDATE TOP (10) HumanResources.Employee  
SET VacationHours = VacationHours * 1.25,  
    ModifiedDate = GETDATE()   
OUTPUT inserted.BusinessEntityID,  
       deleted.VacationHours,  
       inserted.VacationHours,  
       inserted.ModifiedDate  
INTO @MyTableVar;  

--Display the result set of the table variable.  
SELECT EmpID, OldVacationHours, NewVacationHours, ModifiedDate  
FROM @MyTableVar;  
GO  
--Display the result set of the table.  
SELECT TOP (10) BusinessEntityID, VacationHours, ModifiedDate  
FROM HumanResources.Employee;  
GO 



2> Bill Karwin..:

处理此问题的一种方法是在事务中执行此操作,并使SELECT查询对所选行执行更新锁定,直到事务完成.

BEGIN TRAN

SELECT Id FROM Table1 WITH (UPDLOCK)
WHERE AlertDate IS NULL;

UPDATE Table1 SET AlertDate = getutcdate() 
WHERE AlertDate IS NULL;

COMMIT TRAN 

这消除了并发客户端更新SELECT和UPDATE之间选择的行的可能性.

提交事务时,将释放更新锁.

另一种处理方法是使用FOR UPDATE选项为SELECT声明一个游标.然后更新当前CURSOR的当前.以下未经过测试,但应该为您提供基本想法:

DECLARE cur1 CURSOR FOR
  SELECT AlertDate FROM Table1 
  WHERE AlertDate IS NULL
  FOR UPDATE;

DECLARE @UpdateTime DATETIME

SET @UpdateTime = GETUTCDATE()

OPEN cur1;

FETCH NEXT FROM cur1;

WHILE @@FETCH_STATUS = 0
BEGIN

  UPDATE Table1 AlertDate = @UpdateTime
  WHERE CURRENT OF cur1;

  FETCH NEXT FROM cur1;

END


为UPDLOCK +1,它是解决这个问题的正确方法,在短交易中不会导致死锁

3> K. R. ..:

许多年后......

使用OUTPUT子句的公认答案是好的.我不得不挖掘实际的语法,所以这里是:

DECLARE @UpdatedIDs table (ID int)
UPDATE 
    Table1 
SET 
    AlertDate = getutcdate() 
OUTPUT
    inserted.Id
INTO
    @UpdatedIDs
WHERE 
    AlertDate IS NULL;

2015年9月14日新增:

"我可以使用标量变量而不是表变量吗?" 有人可能会问...抱歉,但不,你不能.SELECT @SomeID = ID from @UpdatedIDs如果您需要一个ID ,则必须这样做.



4> Kevin Fairch..:

首先执行UPDATE然后运行'SELECT ID FROM INSERTED'会更容易.

有关更多信息和示例,请查看SQL技巧.



5> Gordon Bell..:

也许更像这样?

declare @UpdateTime datetime

set @UpdateTime = getutcdate()

update Table1 set AlertDate = @UpdateTime where AlertDate is null

select ID from Table1 where AlertDate = @UpdateTime

推荐阅读
臭小子
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有