【问题标题】:Updating Columns in SQL Server using triggers使用触发器更新 SQL Server 中的列
【发布时间】:2017-03-24 10:46:26
【问题描述】:

我有一个由外部应用程序更新的表。我有以下列:

  • 旧读
  • 旧读日期
  • 抄表
  • 读取日期
  • 确认阅读

MeterReading、ReadDate 和 ConfirmReading 由应用程序更新。 ConfirmReading 仅在 MeterReading 超出可接受范围时更新。

我需要以下事情发生:

1) 当 MeterReading 和 ReadDate 在表中更新时,OldReading 和 OldReadDate 应该使用同一个表中的这些值进行更新。

2) 但是,如果 ConfirmReading 也更新了; OldReading 应改为使用此值更新。

3) OldReading 和 OldReadDate 通过上述方式更新后,MeterReading、ConfirmReading 和 ReadDate 应分别设置为 0、0、NULL。

这是我目前所拥有的:

CREATE TRIGGER [dbo].[Set_Old_Streetlight_Readings_to_New] ON [dbo].[M_FRSCHH_STRLGHT_METER]

AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON
    IF UPDATE(MeterReading) AND UPDATE(ConfirmReading)

        BEGIN

            UPDATE [dbo].[M_FRSCHH_STRLGHT_METER]

                SET [OldReading] = [ConfirmReading], [OldReadDate] = [ReadDate]
                WHERE ConfirmReading != 0
        END

ELSE

    IF UPDATE(MeterReading)

        BEGIN

            UPDATE [dbo].[M_FRSCHH_STRLGHT_METER]

                SET OldReading = MeterReading, OldReadDate = ReadDate
                WHERE ConfirmReading = 0

        END

    IF UPDATE(OldReading)
        BEGIN

            UPDATE [dbo].[M_FRSCHH_STRLGHT_METER]

            SET MeterReading = 0, ConfirmReading = 0, ReadDate = NULL, ReadingPhoto = NULL, Reading_Flag = Null
            WHERE MeterReading != 0
    END
END

当 MeterReading 和 Confirm Reading 都更新时,它有点工作,但如果只有 MeterReading 更新,则不是。

TIA,

杰森

【问题讨论】:

  • 我添加了 SQL Server 标签,因为代码看起来像 SQL Server。
  • 首先,触发器更新所有行(考虑WHERE),不仅更新行,对吗?
  • 接下来,SET OldReading =... IF UPDATE(OldReading) 可能会触发递归,如果在 DB 上允许的话。对吗?
  • 这是正确的 Serg

标签: sql sql-server triggers sql-update


【解决方案1】:

我根本看不出这段代码有什么用处。它没有使用inserteddeleted“表”。我希望是这样的:

CREATE TRIGGER [dbo].[Set_Old_Streetlight_Readings_to_New]
    ON [dbo].[M_FRSCHH_STRLGHT_METER]
    AFTER UPDATE
AS
BEGIN
    SET NOCOUNT ON
    IF UPDATE(MeterReading) AND UPDATE(ConfirmReading)
    BEGIN
        UPDATE [dbo].[M_FRSCHH_STRLGHT_METER]
            SET [OldReading] = [ConfirmReading],
                [OldReadDate] = [ReadDate]
            FROM [dbo].[M_FRSCHH_STRLGHT_METER] lm JOIN
                 inserted i
                 ON lm.?? = i.??
            WHERE i.ConfirmReading = 0
        END;
    END;
    . . . 
END;

我不知道使用哪一列将inserted 与行中的数据相匹配。

【讨论】:

  • 嗨,戈登,感谢您的评论。所以我明白你所说的,但表没有被删除或插入,它会不断更新。在 MeterReading 和 ConfirmReading 都更新的地方,脚本可以完美运行。当仅更新 MeterReading 时,它就会失败。我是 SQL Server 的新手,所以要温柔。
  • @JasonPretorius 。 . .您的代码正在更新M_FRSCHH_STRLGHT_METER 中的所有 行。这对我来说似乎不受欢迎。
  • 我同意,我已将其更改为类似于您推荐的代码,但现在存在歧义问题。
【解决方案2】:

首先,使用INSTEAD OF触发器,它更自然地符合您的要求。其次,即使列更新为相同的值,UPDATE() 也会返回 true,根据您的叙述,我认为这不是您想要的。

这是一个示例触发器:

create trigger Set_Old_Streetlight_Readings_to_New
on dbo.M_FRSCHH_STRLGHT_METER
instead of update
as
begin
set nocount on

;with x as (
    select 
        i.OldReading,
        i.OldReadDate,
        i.MeterReading,
        i.ReadDate,
        i.ConfirmReading,
        d.OldReading d_OldReading,
        d.OldReadDate d_OldReadDate,
        d.MeterReading d_MeterReading,
        d.ReadDate d_ReadDate,
        d.ConfirmReading d_ConfirmReading
    from inserted i
    join M_FRSCHH_STRLGHT_METER d on i.<pk> = d.<pk>
        and i.MeterReading <> d.MeterReading and i.ReadDate <> d.ReadDate
)
update x
set
    d_OldReading = case when OldReading <> d_OldReading then ConfirmReading else MeterReading end,
    d_OldReadDate = ReadDate,
    d_MeterReading = 0,
    d_ConfirmReading = 0,
    d_ReadDate = null

END

【讨论】:

  • 我在使用此代码执行时收到“无效列错误”。我将把它作为工作的基础。谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-26
相关资源
最近更新 更多