我们的一位应用程序开发人员向我提出了一个有趣的问题。在下面的代码中,您将看到更新语句将当前列值分配给两个变量,同时还将这些相同的列更新为新值。
\n问题是,是否保证变量@oStart和@oFinish将被分配给[Start]和[Finish]的旧值而不是新值?在测试中,情况确实如此,但是,我想确认这是有保证的行为。
\n我预计答案是“不 - 不能保证”,最终,这取决于优化器所做的决定。无论如何,无论如何,这种模棱两可的代码都是不鼓励的(有更优雅和可读的编写方式),但有兴趣听到每个人的想法。
\n-- Parameters\nDECLARE @StartDate smalldatetime = '2022-01-01',\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0 @EndDate smalldatetime = '2022-12-31';\n\n-- Body\nDECLARE @oStart smalldatetime,\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0 @oFinish smalldatetime;\n\nUPDATE\xc2\xa0 [dbo].[MyTable]\nSET\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0 @oStart = [Start],\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0 @oFinish = [Finish],\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0 [Start] = @StartDate,\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0 [Finish] = @EndDate\nWHERE\xc2\xa0\xc2\xa0 [ID] = 12;\n
Run Code Online (Sandbox Code Playgroud)\n
是的,这是有记录的。@variable
请参阅语法中的文档UPDATE
。
SET @variable = column
...将变量设置为列的更新前值。
(与文档中的对比,SET @variable = column = expression
它将变量设置为赋值后的column = expression
值)。
DECLARE @oldStart SMALLDATETIME,
@oldFinish SMALLDATETIME,
@newStart SMALLDATETIME,
@newFinish SMALLDATETIME;
DECLARE @MyTable TABLE
(
ID INT PRIMARY KEY,
Start SMALLDATETIME,
Finish SMALLDATETIME
)
INSERT @MyTable
VALUES(12, '1900-01-01', '1900-01-31');
UPDATE @MyTable
SET @oldStart = [Start],
@oldFinish = [Finish],
@newStart = [Start] = '2022-01-01',
@newFinish = [Finish] = '2022-12-31'
WHERE [ID] = 12;
SELECT @oldStart AS [@oldStart],
@oldFinish AS [@oldFinish],
@newStart AS [@newStart],
@newFinish AS [@newFinish];
Run Code Online (Sandbox Code Playgroud)
退货
@oldStart | @旧完成 | @新的开始 | @newFinish |
---|---|---|---|
1900-01-01 00:00:00 | 1900-01-31 00:00:00 | 2022-01-01 00:00:00 | 2022-12-31 00:00:00 |
假设ID
是主键,因此UPDATE
保证最多影响一行,那么我个人认为,如果您需要将该值分配给 SQL 变量,那么这种语法就很好。
它优于必须使用子句OUTPUT ... INTO
将这些值存储在某处,然后将SELECT
其后续值分配给变量。
SQL标准规定
在更新 T 的任何行之前,将针对 [table] T 的每一行有效评估 SCL [Set Clause List] 中包含的每个 <set Clause> 的 <update source>
(强调我的)。在您的情况下,这意味着根据标准,@oStart
和必须分别具有和@oFinish
的值,因为它们在更新之前就存在。[Start]
[Finish]
现在,SQL Server 在这方面是否符合标准是一个不同的问题。