Dav*_*cia 41 sql t-sql sql-server sql-server-2008
我想基于一个简单的标准更新一组行,并获取已更改的PK列表.我以为我可以做这样的事情,但我担心可能的并发问题:
SELECT Id FROM Table1 WHERE AlertDate IS NULL;
UPDATE Table1 SET AlertDate = getutcdate() WHERE AlertDate IS NULL;
Run Code Online (Sandbox Code Playgroud)
如果包含在事务中,是否存在可能发生的并发问题?或者有更好的方法吗?
Mar*_*las 72
考虑查看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
Run Code Online (Sandbox Code Playgroud)
Bil*_*win 13
处理此问题的一种方法是在事务中执行此操作,并使SELECT查询对所选行执行更新锁定,直到事务完成.
BEGIN TRAN
SELECT Id FROM Table1 WITH (UPDLOCK)
WHERE AlertDate IS NULL;
UPDATE Table1 SET AlertDate = getutcdate()
WHERE AlertDate IS NULL;
COMMIT TRAN
Run Code Online (Sandbox Code Playgroud)
这消除了并发客户端更新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
Run Code Online (Sandbox Code Playgroud)
K. *_*R. 12
许多年后......
使用OUTPUT子句的公认答案是好的.我不得不挖掘实际的语法,所以这里是:
DECLARE @UpdatedIDs table (ID int)
UPDATE
Table1
SET
AlertDate = getutcdate()
OUTPUT
inserted.Id
INTO
@UpdatedIDs
WHERE
AlertDate IS NULL;
Run Code Online (Sandbox Code Playgroud)
2015年9月14日新增:
"我可以使用标量变量而不是表变量吗?" 有人可能会问...抱歉,但不,你不能.SELECT @SomeID = ID from @UpdatedIDs如果您需要一个ID ,则必须这样做.
也许更像这样?
declare @UpdateTime datetime
set @UpdateTime = getutcdate()
update Table1 set AlertDate = @UpdateTime where AlertDate is null
select ID from Table1 where AlertDate = @UpdateTime
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
93274 次 |
| 最近记录: |