我正在为SQL Server 2012数据库设计一个新的数据库模式。
每个表都应该有两个名为modified
和created
的额外列,这些列应该在插入或更新行时自动更改。
我不知道怎样才能到达那里。
我认为触发器是处理它的最佳方式。
我试图找到触发器的例子..但是我发现在另一个表中插入数据的教程等。
我认为这是一个很常见的场景,但我还没有找到答案。
created
列很简单 - 只是一个DATETIME2(3)
列,默认约束在插入新行时设置:
Created DATETIME2(3)
CONSTRAINT DF_YourTable_Created DEFAULT (SYSDATETIME())
因此,当您在YourTable
中插入一行并且没有为Created
指定值时,它将被设置为当前日期和时间。
modified
有点工作,因为你需要为AFTER UPDATE
案例编写一个触发器并更新它 - 你不能声明地告诉SQL Server为你做这个....
Modified DATETIME2(3)
然后
CREATE TRIGGER updateModified
ON dbo.YourTable
AFTER UPDATE
AS
UPDATE dbo.YourTable
SET modified = SYSDATETIME()
FROM Inserted i
WHERE dbo.YourTable.PrimaryKey = i.PrimaryKey
您需要加入Inserted
伪表,其中包含使用您的主表上的基表更新的所有行。
而且你必须为你希望拥有AFTER UPDATE
列的每个表创建这个modified
触发器。
通常,您可以拥有以下列:
其中LastModifiedBy
和CreatedBy
是对users
表(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(如read-only
或read and write
)设置。这些东西有点用户友好:
EXEC sp_set_session_context 'user_id', 4;
SELECT SESSION_CONTEXT(N'user_id');
一个不错的example。
注意,上面工作正常,但并非在所有情况下,我失去了很多时间,发现这有用:
create TRIGGER yourtable_update_insert
ON yourtable
AFTER UPDATE
as
begin
set nocount on;
update yourtable set modified=getdate(), modifiedby = suser_sname()
from yourtable t
inner join inserted i on t.uniqueid=i.uniqueid
end
go
你需要set nocount on;
,否则你会得到错误:
Microsoft SQL Server Management Studio
没有更新行。
第5行中的数据未提交。错误源:Microsoft.SqlServer.Management.DataTools。错误消息:更新或删除的行值不会使行唯一,也不会更改多行(2行)。
更正错误并重试,或按ESC取消更改。
好的帮助