想像这样一个简单的更新存储过程:
CREATE PROCEDURE [UpdateMyTable] (
@Id int,
@ModifiedOn datetime,
@GeneratedOn datetime
)
AS
UPDATE
[MyTable]
SET
[ModifiedOn] = @ModifiedOn
WHERE
[Id] = @Id AND [ModifiedOn] <= @GeneratedOn
现在,要基于ModifiedOn的先前值返回结果,我将其更改为:
ALTER PROCEDURE [UpdateMyTable] (
@Id int,
@ModifiedOn datetime,
@GeneratedOn datetime
)
AS
DECLARE @PreviousModifiedOn datetime
UPDATE
[MyTable]
SET
[ModifiedOn] = @ModifiedOn,
@PreviousModifiedOn = [ModifiedOn]
WHERE
[Id] = @Id AND [ModifiedOn] <= @GeneratedOn
IF @PreviousModifiedOn <= @GeneratedOn
SELECT @ModifiedOn
ELSE
SELECT -1
在SET部分中将@PreviousModifiedOn变量填充为ModifiedOn的先前值是否安全?还是在将ModifiedOn值保存到变量之前更改它?
使用OUTPUT
进行相同的查询:
ALTER PROCEDURE [UpdateMyTable] (
@Id int,
@ModifiedOn datetime,
@GeneratedOn datetime
)
AS
DECLARE @PreviousModifiedOn AS TABLE (ModifiedOn datetime)
UPDATE
[MyTable]
SET
[ModifiedOn] = @ModifiedOn
OUTPUT
Deleted.[ModifiedOn] INTO @PreviousModifiedOn
WHERE
[Id] = @Id AND [ModifiedOn] <= @GeneratedOn
IF EXISTS (SELECT * FROM @PreviousModifiedOn WHERE [ModifiedOn] <= @GeneratedOn)
SELECT @ModifiedOn
ELSE
SELECT -1
看来OUTPUT
是解决问题的正确方法,但是由于变量表,我认为它的性能成本更高。
所以我的问题是...为什么使用OUTPUT
比我的解决方案好?我的解决方案有什么问题吗?在性能和速度上哪个更好?
答案 0 :(得分:3)
我相信这是安全的。尽管变量赋值是专有扩展,但SET子句的其余部分遵循此处的SQL标准-所有赋值均按 进行计算,就像它们并行发生一样。也就是说,赋值右边的所有表达式都是基于所有列的更新前值来计算的。
例如为什么UPDATE Table SET A=B, B=A
会交换两列的内容,而不是将它们都设置为等于先前的B
。
对我来说,要警惕的一件事是UPDATE
可能执行了 no 分配(由于WHERE
子句),因此仍然是NULL
,或者可能已经执行了多个分配;在后一种情况下,您的变量将设置为先前的值之一,但不能保证它将保留哪个 row 值。
答案 1 :(得分:3)
这不是必需的,因为MS SQL Server 2005可以在这种情况下使用OUTPUT。
If Button1.CheckState = CheckState.Checked Then
Button1.Image = My.Resources.icon1
Else
Button1.Image = My.Resources.icon2
End If