【问题标题】:How do I add the row update time and row update user to a table?如何将行更新时间和行更新用户添加到表中?
【发布时间】:2017-05-09 20:48:10
【问题描述】:

我有一个表,其中定义了创建日期和创建用户字段,似乎正在工作。

但我在创建功能正常的行更新日期时间和按字段更新的行时遇到了困难。

我希望这些字段如何工作:当有人更新表中的记录时,正在更新的记录会记录日期/时间和用户名。

这是我失败的触发器创建语法,我错误地改编自 Stack Overflow 上的答案:

我应该指出,在许多其他示例中,我不明白“插入”表的来源。也不是为什么它和内部连接有效。

CREATE TRIGGER mkt.Update_tbl_fTesting
  ON mkt.tbl_fTesting
  FOR UPDATE
AS

BEGIN
  SET NOCOUNT ON;

  UPDATE mkt.tbl_fTesting
    SET RowUpdateDateTime = GetDate()
      , RowUpdateBy = coalesce(SUSER_SNAME(), '?')
    FROM mkt.tbl_fTesting
    INNER JOIN inserted
    ON tbl_fTesting.tbl_fTestingIdentity = inserted.ID;
END
GO

执行触发器创建语法的错误是:

列名“ID”无效

这是我按预期工作的表创建语法:

USE [ObscuredDatabase]
GO

DROP TABLE [mkt].[tbl_fTesting]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [mkt].[tbl_fTesting](
    [tbl_TestingIdentity] [bigint] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL,
  [Produce] [nvarchar] (25) NOT NULL,
  [Color] [nvarchar] (25) NOT NULL,
  [RowCreateDateTime] [datetime] NULL DEFAULT (getdate()),
  [RowCreateBy] [nvarchar](max) NULL DEFAULT (coalesce(suser_sname(),'?')),
  [RowUpdateDateTime] [datetime] NULL,
  [RowUpdateBy] [nvarchar](max) NULL
PRIMARY KEY CLUSTERED 
(
    [tbl_fTestingIdentity] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [SECONDARY]
) ON [SECONDARY]

GO

【问题讨论】:

    标签: sql sql-server tsql sql-server-2016


    【解决方案1】:

    好吧,你的表的主键不叫ID,叫tbl_TestingIdentity所以在插入时你需要使用这个列名。 (inserted.tbl_TestingIdentity)

    【讨论】:

    • 谢谢 Rigerta,您的回答绝对正确,对我有用
    【解决方案2】:

    我应该注意,我不明白“插入”表的来源 在许多其他例子中。也不是为什么它和内部连接有效。

    你真的很亲密。将inserted 表视为一个临时表,其中包含将要插入或更新的记录。它与接收更新的表具有相同的结构。

    所以您需要做的就是使用inserted 表中的正确列名,这将与JOIN 中的mkt.tbl_fTesting 的列名匹配:

    CREATE TRIGGER mkt.Update_tbl_fTesting
      ON mkt.tbl_fTesting
      FOR UPDATE
    AS
    
    BEGIN
      SET NOCOUNT ON;
    
      UPDATE FTest
        SET RowUpdateDateTime = GetDate()
          , RowUpdateBy = coalesce(SUSER_SNAME(), '?')
        FROM mkt.tbl_fTesting FTest
        INNER JOIN inserted
        ON FTest.tbl_fTestingIdentity = inserted.tbl_fTestingIdentity;
    END
    GO
    

    编辑更多信息:

    想象一个简单的表格,Clothes

    ID | Type  | Color | RowUpdateDateTime
    1  | Sock  | Pink  | NULL
    2  | Sock  | Red   | NULL
    3  | Shirt | Blue  | NULL
    

    然后你运行一个简单的更新:

    UPDATE Clothes
    SET    Color = 'Green'
    WHERE  Type = 'Sock'
    

    在执行时,将创建一个inserted 表,其中包含新行:

    ID | Type  | Color | RowUpdateDateTime
    1  | Sock  | Green | NULL
    2  | Sock  | Green | NULL
    

    然后您的触发器将触发对RowUpdateDateTime 列的更新:

    UPDATE C
    SET RowUpdateDateTime = GETDATE()
    FROM Clothes C
    INNER JOIN inserted i ON i.ID = C.ID;
    

    由于连接谓词i.ID = C.ID,将仅更改受原始更新影响的行的修改日期

    最终Clothes 表:

    ID | Type  | Color | RowUpdateDateTime
    1  | Sock  | Green | 2017-05-09 16:32:09.873
    2  | Sock  | Green | 2017-05-09 16:32:09.873
    3  | Shirt | Blue  | NULL
    

    【讨论】:

    • 那么这是否意味着插入的表在更新时基本上只有一行?
    • @ChrisG 不完全......它将具有与原始更新相同的行数。这就是为什么你必须在一个条件下实际加入它。将 X 个原始行链接到 X 个插入行。希望这是有道理的。
    • 这有点道理,但我只需要做一些独立的阅读和研究。谢谢!
    • @ChrisG 很高兴为您提供帮助。我还添加了更多解释。 GL给你。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-11
    • 1970-01-01
    • 1970-01-01
    • 2018-07-03
    • 1970-01-01
    • 2022-12-16
    • 2013-02-25
    相关资源
    最近更新 更多