为什么在这段代码中@changed是正确的,但@ changed2不正确?目的是确定列值是否在update语句中发生更改。我没有找到任何可以解释这个细节的事情。
如果我不得不猜测,SQL Server将首先使用要更新的行的当前状态来设置变量,当它完成时它将实际更新它。这就是为什么@ changed2为0,在解析@ changed2变量时,VALUE列尚未更新,因此我们必须使用@newValue。
IF Object_id('tempdb..#tmpTest') IS NOT NULL
DROP TABLE #tmptest;
CREATE TABLE #tmptest
(
test_id INT NOT NULL IDENTITY(1, 1),
value VARCHAR(20)
);
INSERT INTO #tmptest
(value)
VALUES ('hello');
然后多次运行此代码(您可以多次运行它,但不要再执行上面的代码!):
--then run this multiple times:
DECLARE @oldValue VARCHAR(20),
@newValue VARCHAR(20) = (SELECT value
FROM #tmptest
WHERE test_id = 1),
@changed BIT,
@changed2 BIT
--alternate values:
IF( @newValue = 'hello' )
SET @newValue = 'goodbye'
ELSE
SET @newValue = 'hello'
--see current data
SELECT *
FROM #tmptest;
--update
UPDATE #tmptest
SET value = @newValue,
@oldValue = value,
@changed = CASE
WHEN @oldValue != @newValue THEN 1
ELSE 0
END,
@changed2 = CASE
WHEN @oldValue != value THEN 1
ELSE 0
END
WHERE test_id = 1;
--see changed data:
SELECT *
FROM #tmptest;
SELECT @oldValue oldValue,
@newValue newValue,
@changed changed,
@changed2 changed2
感谢您的时间。
答案 0 :(得分:1)
执行更新时,如果需要知道原始记录上的值,SQL Server将在任何更新到位之前读取原始数据。因此,在您的示例中,过程将是这样的:
Read value as @OldValue
Compare @oldValue and value
Set @changed
Set @changed2
Update value from @newValue
在某些代码中涉及读取,更新和返回更新前值的某些代码实际上会依赖此行为,从而阻止其他进程检索相同的值。