【问题标题】:Auto update time in SQL ServerSQL Server 中的自动更新时间
【发布时间】:2012-01-04 14:42:05
【问题描述】:

我想在我的表中有两列来存储添加时间和更新时间。顾名思义,添加时间是第一次添加行的时间;更新时间是最后一次更新行。我可以首先通过默认值GETDATE() 来实现。至于第二个,@Jeremy 建议在这里使用触发器:

On Update: Auto Update Date/Time Field

  1. 有没有更简单的方法?
  2. 如果我实现了一个触发器,这是否意味着必须执行两条 UPDATE 语句(或一条 INSERT 和一条 UPDATE,以防刚刚创建行)?

谢谢。

编辑:对于问题的第二部分,这是我数据库中的触发器:

CREATE TRIGGER [dbo].[TR_AddUpdateTime]
   ON [dbo].[AddUpdateTime]
   AFTER UPDATE
AS 
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    -- Insert statements for trigger here

    UPDATE r
       SET UpdateTime = GETDATE()
      FROM AddUpdateTime r
      JOIN inserted i
        ON i.Id = r.Id
END

这是否意味着每当我对 AddUpdateTime 表进行更新时都会执行额外的更新语句,或者 MSSQL 足够聪明,可以识别我正在更新同一条记录并同时保存这两项更改?

【问题讨论】:

  • 您是否总是通过存储过程更新/插入?你可以用它来插入时间。
  • 不,我实际上使用的是实体框架。
  • 我编辑了我的答案以获得实体框架的选项。

标签: sql-server tsql entity-framework auto-update


【解决方案1】:
  1. 其他方式:

    • 使用存储过程包装更新
    • 你可以做UPDATE MyTable SET ..., UpdatedWhen = DEFAULT...

  2. 您需要一个本身还有一个 UPDATE 的 UPDATE 触发器。在表上使用默认值意味着您不需要 INSERT 触发器

【讨论】:

  • 正如我在对@paulsm4 的回答的评论中提到的,我不想使用存储过程。我也不想在想要更新记录时手动设置 UpdateTime,因为我希望解决方案具有通用性,以便在许多表中使用它。
  • 至于您的第二条评论,我只使用默认值作为添加时间,因为它仅在第一次创建记录时设置。但是每当我对记录进行任何更改时,都需要更新更新时间。
  • @Promather:您可以在更新中使用 DEFAULT 关键字来设置它。因此,如果默认值为 GETDATE(),那么 UpdatedWhen 将使用最新日期更新。即使您使用触发器,这也意味着 GETDATE 仅在约束中提及:不在代码中。
  • 是的,这很好。但是我仍然需要始终将 UpdatedWhen = DEFAULT 添加到每个 UPDATE 语句中,这不是一个好习惯。
  • @Promather:听起来您在“添加时间”上的默认值将处理 INSERT 上的该字段。正如 gbn 建议的那样,UPDATE 触发器将在更新行时触发。反过来,触发器需要执行 UPDATE 来设置“更新时间”。有意义吗?
【解决方案2】:
  1. 您可以确保所有插入和更新都通过一个插入时间的存储过程。
  2. 不,插入触发器将修改值,使其只有一条语句。

编辑:对于实体框架,您能否实现 OnSavingChanges 事件以插入更新时间字段 (see here)?这将责任从数据库转移到您可能会或可能不会感到满意的代码。

【讨论】:

  • 所以似乎有些混乱。您说触发器不会导致执行额外的 UPDATE 语句,但这与上面@gbn 所说的相反!
  • 我为您编辑了我的问题,以查看我添加到数据库中的触发器。
【解决方案3】:

在实体框架中,可以使用分部类来扩展业务逻辑。在这种情况下,您可以使用 OnPropertyChanged 将更新时间设置为 DateTime.Now。您可以将此article on MSDN 用作指导。

【讨论】:

    【解决方案4】:

    1) “自动更新”和“触发器”听起来并不像要走的路。

    2) SQL Server 有一个(相对较新的)“合并”语句。但这听起来也不是您想要的。

    3) 代替:

    a) 如果主键不存在(如果“新”),则插入。在这种情况下,第一次 = 最后一次 = GETDATE()。

    b) 否则,如果主键已经存在,则更新。您的更新将仅更新“上次”列(以及您需要为此记录更新的其余字段。

    4) 或许您可以将此逻辑包装在存储过程中?

    5) 再次——关键是更新BOTH“第一次”和“最后一次*,FIRST TIME,然后更新ONLY em>“最后一次”所有 SUBSEQUENT 次。

    【讨论】:

    • 好吧,我希望我的记录能够自动更新,而不必编写存储过程,因为我正在使用实体框架并且我不确定如何让实体框架使用我的存储过程进行插入/更新记录。
    【解决方案5】:
    1. 它们可能是一种更简单的方法,但使用触发器会更有效,并且无论如何插入或更新记录(来自 .net 代码或直接表插入/更新),这两个字段都会被填充

    2. 为了保证每次只有一个触发器被触发,结合插入和更新触发器

       CREATE TRIGGER <trigger name> ON TableA for INSERT,UPDATE
      

      并进行条件检查以区分两个动作

       IF UPDATE
      

    【讨论】:

      猜你喜欢
      • 2011-08-10
      • 2010-09-07
      • 1970-01-01
      • 1970-01-01
      • 2021-03-06
      • 1970-01-01
      • 1970-01-01
      • 2011-06-03
      • 2013-04-03
      相关资源
      最近更新 更多