通过触发器

时间:2015-09-02 08:09:56

标签: sql-server tsql sql-update database-trigger

我试图用另一个表中的触发器更新表。我认为这将是一个非常简单的查询,但我第一次提出的查询不起作用,我不明白为什么。

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,
)

添加交易时,我希望更新Vehicle表。如果添加的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]); 更新,请使用那个..如果不是..使用当前。但我似乎错过了一些东西,因为它没有更新到最新的日期。它确实匹配该特定车辆的一个交易,但不匹配最新的交易。

有效的查询:

for IP in $IPLIST; do
    ssh teacher@$IP 'killall -u testaccount001'
done

所以我有一个有效的解决方案,它甚至可能会变得更好(没有时间用大插入它),但它会让我不知道为什么第一个它不起作用!

任何人都可以启发我吗?

1 个答案:

答案 0 :(得分:1)

  

为什么第一个不起作用

由于使用FROM子句的UPDATE的Microsoft扩展的一个很棒的方面:

  

在指定FROM子句时要小心,以提供更新操作的条件。 UPDATE语句的结果是未定义如果语句包含FROM子句未指定的方式,只有一个值可用于每个列事件,即已更新,即UPDATE语句不是确定性

(我强调)。

也就是说,如果inserted中的多行与Vehicle中的同一行匹配,那么它将是未定义的哪个行将用于应用更新 - 以及所有计算在SET子句中计算“好像”它们都是并行计算的 - 所以它不像第二次尝试更新同一行会在第一次尝试时观察到结果 - {的当前值{1}}可以观察到的列始终是原始值。

在ANSI标准SQL中,您必须在不使用DateUsed扩展名的情况下编写UPDATE,因此必须编写相关的子查询,例如:

FROM

在相同的情况下,很好地会给出一个关于子查询返回多个值的错误(对于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扩展名很有用 - 我只是希望它能引发这种情况的警告。