更新触发器使用的日期
Update DateUsed by trigger
我正在尝试使用另一个 table 的触发器更新 table。我认为这将是一个非常简单的查询,但我最初提出的查询不起作用,我不明白为什么。
CREATE TABLE [dbo].[Vehicle](
[id] [int] IDENTITY(1,1) NOT NULL,
[plate] [nvarchar](50) NOT NULL,
[name] [nvarchar](50) NOT NULL,
[dateUsed] [datetime] NULL
)
CREATE TABLE [dbo].[Transaction](
[id] [int] IDENTITY(1,1) NOT NULL,
[vehicleId] [int] NOT NULL,
[quantity] [float] NOT NULL,
[dateTransaction] [datetime] NOT NULL,
)
添加交易后,我希望更新车辆table。如果添加的 dateTransaction
晚于 dateUsed
,则应对其进行更新,以便 dateUsed
字段始终包含该特定车辆的最新日期。
我认为这个触发器应该可以解决问题..但它没有:
UPDATE [Vehicle]
SET [dateUsed] =
CASE
WHEN [dateUsed] < [Transaction].[dateTransaction]
OR [dateUsed] IS NULL
THEN [Transaction].[dateTransaction]
ELSE [dateUsed]
END
FROM [Transaction]
WHERE [Vehicle].[id]=[Transaction].[vehicleId]
我觉得不错...它应该遍历所有新插入的记录并更新 dateUsed
字段。如果 dateTransaction
较新,则使用那个。如果不是。使用当前的。但我似乎遗漏了一些东西,因为它没有更新到最新日期。它确实匹配该特定车辆的其中一项交易,但不匹配最新的交易。
有效的查询:
UPDATE [Vehicle]
SET [dateUsed] = InsertedPartitioned.[dateTransaction]
FROM [Vehicle]
LEFT JOIN (
SELECT
[vehicleId],
[dateTransaction],
ROW_NUMBER() OVER(PARTITION BY [VehicleId] ORDER BY [dateTransaction] DESC) AS RC
FROM [Inserted]) AS InsertedPartitioned
ON InsertedPartitioned.RC=1
AND InsertedPartitioned.[vehicleId]=[Vehicle].[id]
WHERE InsertedPartitioned.[vehicleId] IS NOT NULL
AND ([Vehicle].[dateUsed] IS NULL
OR InsertedPartitioned.[dateTransaction] > [Vehicle].[dateUsed]);
所以我有一个可行的解决方案,它甚至可能会变得更好(没有用大的插入物计时)但是它让我不知道为什么第一个它不起作用!
任何人都可以 'enlighten me'?
why the first it not working
由于 Microsoft 对 UPDATE
的扩展使用了 FROM
子句:
Use caution when specifying the FROM
clause to provide the criteria for the update operation. The results of an UPDATE
statement are undefined if the statement includes a FROM
clause that is not specified in such a way that only one value is available for each column occurrence that is updated, that is if the UPDATE
statement is not deterministic.
(我的重点)。
也就是说,如果 inserted
中的不止一行与 Vehicle
中的同一行相匹配,则它是未定义的 哪一个 行将用于应用update - SET
子句中的所有计算都是计算 "as if" 它们都是并行计算的 - 所以第二次尝试更新同一行不会观察到第一次尝试的结果 - DateUsed
列当前可观测值始终为原始值
在 ANSI 标准 SQL 中,您必须在不使用 FROM
扩展的情况下编写 UPDATE
,因此必须编写相关的子查询,例如:
UPDATE [Vehicle]
SET [dateUsed] = COALESCE((SELECT dateUsed FROM inserted i
WHERE i.VehicleId = Vehicle.Id and
(i.dateUsed > Vehicle.DateUsed or
Vehicle.DateUsed IS NULL),
dateUsed)
WHERE [id] IN (select [vehicleId] FROM inserted)
在同样的情况下,如果子查询返回多个值(COALESCE
中的值,而不是 IN
中的值),则很好地给出一个错误,并且从而为您提供有关它为何不起作用的线索。
但是,不可否认,FROM
扩展很有用 - 我只是希望它能针对这种情况触发警告。
我正在尝试使用另一个 table 的触发器更新 table。我认为这将是一个非常简单的查询,但我最初提出的查询不起作用,我不明白为什么。
CREATE TABLE [dbo].[Vehicle](
[id] [int] IDENTITY(1,1) NOT NULL,
[plate] [nvarchar](50) NOT NULL,
[name] [nvarchar](50) NOT NULL,
[dateUsed] [datetime] NULL
)
CREATE TABLE [dbo].[Transaction](
[id] [int] IDENTITY(1,1) NOT NULL,
[vehicleId] [int] NOT NULL,
[quantity] [float] NOT NULL,
[dateTransaction] [datetime] NOT NULL,
)
添加交易后,我希望更新车辆table。如果添加的 dateTransaction
晚于 dateUsed
,则应对其进行更新,以便 dateUsed
字段始终包含该特定车辆的最新日期。
我认为这个触发器应该可以解决问题..但它没有:
UPDATE [Vehicle]
SET [dateUsed] =
CASE
WHEN [dateUsed] < [Transaction].[dateTransaction]
OR [dateUsed] IS NULL
THEN [Transaction].[dateTransaction]
ELSE [dateUsed]
END
FROM [Transaction]
WHERE [Vehicle].[id]=[Transaction].[vehicleId]
我觉得不错...它应该遍历所有新插入的记录并更新 dateUsed
字段。如果 dateTransaction
较新,则使用那个。如果不是。使用当前的。但我似乎遗漏了一些东西,因为它没有更新到最新日期。它确实匹配该特定车辆的其中一项交易,但不匹配最新的交易。
有效的查询:
UPDATE [Vehicle]
SET [dateUsed] = InsertedPartitioned.[dateTransaction]
FROM [Vehicle]
LEFT JOIN (
SELECT
[vehicleId],
[dateTransaction],
ROW_NUMBER() OVER(PARTITION BY [VehicleId] ORDER BY [dateTransaction] DESC) AS RC
FROM [Inserted]) AS InsertedPartitioned
ON InsertedPartitioned.RC=1
AND InsertedPartitioned.[vehicleId]=[Vehicle].[id]
WHERE InsertedPartitioned.[vehicleId] IS NOT NULL
AND ([Vehicle].[dateUsed] IS NULL
OR InsertedPartitioned.[dateTransaction] > [Vehicle].[dateUsed]);
所以我有一个可行的解决方案,它甚至可能会变得更好(没有用大的插入物计时)但是它让我不知道为什么第一个它不起作用!
任何人都可以 'enlighten me'?
why the first it not working
由于 Microsoft 对 UPDATE
的扩展使用了 FROM
子句:
Use caution when specifying the
FROM
clause to provide the criteria for the update operation. The results of anUPDATE
statement are undefined if the statement includes aFROM
clause that is not specified in such a way that only one value is available for each column occurrence that is updated, that is if theUPDATE
statement is not deterministic.
(我的重点)。
也就是说,如果 inserted
中的不止一行与 Vehicle
中的同一行相匹配,则它是未定义的 哪一个 行将用于应用update - SET
子句中的所有计算都是计算 "as if" 它们都是并行计算的 - 所以第二次尝试更新同一行不会观察到第一次尝试的结果 - DateUsed
列当前可观测值始终为原始值
在 ANSI 标准 SQL 中,您必须在不使用 FROM
扩展的情况下编写 UPDATE
,因此必须编写相关的子查询,例如:
UPDATE [Vehicle]
SET [dateUsed] = COALESCE((SELECT dateUsed FROM inserted i
WHERE i.VehicleId = Vehicle.Id and
(i.dateUsed > Vehicle.DateUsed or
Vehicle.DateUsed IS NULL),
dateUsed)
WHERE [id] IN (select [vehicleId] FROM inserted)
在同样的情况下,如果子查询返回多个值(COALESCE
中的值,而不是 IN
中的值),则很好地给出一个错误,并且从而为您提供有关它为何不起作用的线索。
但是,不可否认,FROM
扩展很有用 - 我只是希望它能针对这种情况触发警告。