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列的每个表创建此触发器.
通常,您可以拥有以下列:
where LastModifiedBy和CreatedBy是对userstable(UserID)的引用,而LastModifiedOn和CreatetOn列是日期和时间列.
您有以下选择:
没有触发器的解决方案 - 我已经在某处读过" 编写触发器的最佳方法是不写这样的. "你应该知道它们通常会损害性能.所以,如果你可以避免它们,最好这样做,即使使用触发器在某些情况下看起来最简单.
因此,只需编辑所有您INSERT和UPDATE语句以包含当前UserID和当前日期和时间.如果user ID无法定义(匿名用户),则可以使用0而不是列的默认值(如果未user ID指定则将使用NULL).当您看到NULL插入值时,您应该找到"有罪"语句并进行编辑.
带触发器的解决方案 - 您可以创建AFTER INSERT, UPDATE触发器并在那里填充用户列.在触发器的上下文中获取当前日期和时间很容易(GETUTCDATE()例如使用).这里的问题是触发器不允许传递/接受参数.因此,由于您没有插入user ID值,因此无法将其传递给触发器.如何找到当前用户?
您可以使用SET CONTEXT_INFO和CONTEXT_INFO.在您insert和所有update语句之前,您必须使用它SET CONTEXT_INFO来添加current user ID到当前上下文,并在触发器中使用该CONTEXT_INFO函数来提取它.
因此,当使用触发器时,您再次需要编辑所有的INSERT和UPDATE子句 - 这就是我不想使用它们的原因.
无论如何,如果您只需要具有日期和时间列而不是按列创建/修改,则使用触发器会更耐用,更容易,因为您现在和将来都不会编辑任何其他语句.
随着SQL Server 2016我们现在可以使用SESSION_CONTEXT函数读取会话详细信息.使用sp_set_session_context(as read-only或read and write)设置详细信息.这些东西有点用户友好:
EXEC sp_set_session_context 'user_id', 4;
SELECT SESSION_CONTEXT(N'user_id');
Run Code Online (Sandbox Code Playgroud)
一个很好的例子.