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
是对users
table(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)
一个很好的例子.