如何在SQL Server表中添加"上次修改"和"已创建"列?

ste*_*evo 32 t-sql sql-server triggers sql-server-2012

我正在为SQL Server 2012数据库设计一个新的数据库模式.

每个表都应该调用两个额外的列modified,created这些列应该在插入或更新行时自动更改.

我不知道怎样才能到达那里.

我认为触发器是处理它的最佳方式.

我试图找到触发器的例子..但是我发现在另一个表中插入数据的教程等.

我认为这是一个很常见的场景,但我还没有找到答案.

mar*_*c_s 46

created列很简单 - 只是一个DATETIME2(3)具有默认约束的列,在插入新行时会设置该列:

Created DATETIME2(3) 
   CONSTRAINT DF_YourTable_Created DEFAULT (SYSDATETIME())
Run Code Online (Sandbox Code Playgroud)

因此,当您插入一行YourTable而不指定值时Created,它将被设置为当前日期和时间.

modified是一个更多的工作,因为您需要为AFTER UPDATE案例编写一个触发器并更新它 - 您不能声明性地告诉SQL Server为您执行此操作....

Modified DATETIME2(3)
Run Code Online (Sandbox Code Playgroud)

然后

CREATE TRIGGER updateModified
ON dbo.YourTable
AFTER UPDATE 
AS
   UPDATE dbo.YourTable
   SET modified = SYSDATETIME()
   FROM Inserted i
   WHERE dbo.YourTable.PrimaryKey = i.PrimaryKey
Run Code Online (Sandbox Code Playgroud)

您需要加入Inserted伪表,该伪表包含在该表的主键上使用基表更新的所有行.

并且您必须AFTER UPDATE为要包含modified列的每个表创建此触发器.

  • 非常感谢@marc_s!再次!非常感谢您的帮助!我很想展示一个小的demo sql脚本,人们可以复制和修改它,但它很大的评论.只有一个提示.我发现默认约束的简单方法是`CREATE TABLE [dbo].[Table1]([created] [datetime2](3)NOT NULL CONSTRAINT [DF_Table1_created] DEFAULT(sysdatetime()),...)`plus触发`CREATE TRIGGER updateModified`并完成!还有一点提示.触发器名称对于架构中的表必须是唯一的.`CREATE TRIGGER dbo.Table1_updateModified`.干杯斯蒂芬 (3认同)

got*_*tqn 9

通常,您可以拥有以下列:

  • LastModifiedBy
  • LastModifiedOn
  • 由...制作
  • 创建于

where LastModifiedByCreatedBy是对userstable(UserID)的引用,而LastModifiedOnCreatetOn列是日期和时间列.

您有以下选择:

  1. 没有触发器的解决方案 - 我已经在某处读过" 编写触发器的最佳方法是不写这样的. "你应该知道它们通常会损害性能.所以,如果你可以避免它们,最好这样做,即使使用触发器在某些情况下看起来最简单.

    因此,只需编辑所有您INSERTUPDATE语句以包含当前UserID和当前日期和时间.如果user ID无法定义(匿名用户),则可以使用0而不是列的默认值(如果未user ID指定则将使用NULL).当您看到NULL插入值时,您应该找到"有罪"语句并进行编辑.

  2. 带触发器的解决方案 - 您可以创建AFTER INSERT, UPDATE触发器并在那里填充用户列.在触发器的上下文中获取当前日期和时间很容易(GETUTCDATE()例如使用).这里的问题是触发器不允许传递/接受参数.因此,由于您没有插入user ID值,因此无法将其传递给触发器.如何找到当前用户?

    您可以使用SET CONTEXT_INFOCONTEXT_INFO.在您insert和所有update语句之前,您必须使用它SET CONTEXT_INFO来添加current user ID到当前上下文,并在触发器中使用该CONTEXT_INFO函数来提取它.

因此,当使用触发器时,您再次需要编辑所有的INSERTUPDATE子句 - 这就是我不想使用它们的原因.

无论如何,如果您只需要具有日期和时间列而不是按列创建/修改,则使用触发器会更耐用,更容易,因为您现在和将来都不会编辑任何其他语句.


随着SQL Server 2016我们现在可以使用SESSION_CONTEXT函数读取会话详细信息.使用sp_set_session_context(as read-onlyread and write)设置详细信息.这些东西有点用户友好:

EXEC sp_set_session_context 'user_id', 4;  
SELECT SESSION_CONTEXT(N'user_id');  
Run Code Online (Sandbox Code Playgroud)

一个很好的例子.