(SQL Server 2014 速成版)
你好,
我参考这篇文章:http: //msdn.microsoft.com/en-gb/magazine/cc164047.aspx
我有这个 AFTER INSERT、UPDATE、DELETE 触发器来设置或更新几个表中的 DateCreated、DateModified 和 WhoUpdatedID 列(稍后添加删除处理):
CREATE TRIGGER [dbo].[TR_dim_TypeOfClaim_Audit]
ON [dbo].[dim_TypeOfClaim]
AFTER INSERT, UPDATE, DELETE
AS
SET NOCOUNT ON
DECLARE @event_type [char]
--Get Event Type
IF EXISTS(SELECT * FROM inserted)
IF EXISTS(SELECT * FROM deleted)
SELECT @event_type = 'U'
ELSE
SELECT @event_type = 'I'
ELSE
IF EXISTS(SELECT * FROM deleted)
SELECT @event_type = 'D'
ELSE
--no rows affected - cannot determine event
SELECT @event_type = 'K'
IF @event_type = 'I' BEGIN
--Date Created
UPDATE t
SET DateCreated = GETDATE()
FROM INSERTED e
JOIN [dbo].[dim_TypeOfClaim] t ON e.[TypeOfClaimID] = t.[TypeOfClaimID]
;
SELECT @event_type = 'U' --also do UPDATE processing
END
IF @event_type = 'U' BEGIN
--Date Modified
UPDATE t
SET DateModified = GETDATE()
FROM INSERTED e
JOIN [dbo].[dim_TypeOfClaim] t ON e.[TypeOfClaimID] = t.[TypeOfClaimID]
--WhoModifiedID
UPDATE t
SET WhoModifiedID = u.UserID
FROM INSERTED e
JOIN [dbo].[dim_TypeOfClaim] t ON e.[TypeOfClaimID] = t.[TypeOfClaimID]
JOIN [dbo].[dim_Users] u ON u.[Username] = dbo.udfUserName()
END
IF @event_type = 'D' BEGIN
no_op: --Nothing for now
END
GO
DateCreated、DateModified 和 WhoUpdatedID 的完整性规则不为 NULL。这在技术上是正确的,但最终用户永远不会输入。这会在添加新记录时导致错误。
我应该将这些列更改为允许的 NULL,还是将触发器更改为 INSTEAD?我不确定这里的最佳做法。
如果这很重要,我打算稍后通过触发器或更改跟踪对所有数据更改进行全面审核(我需要阅读更改跟踪以查看它是否满足我的需求)。
谢谢您的帮助...
更新:
@Bogdan:对不起,我的评论不清楚。根据到目前为止每个人的反馈,这是我目前拥有的:
1) 我将 DateCreated、DateModified 和 WhoModifiedID 保留为 NOT NULL
2) 我分别创建了默认值 getdate()、getdate() 和 0。所有值都只是为了通过新记录的 NOT NULL 约束。我想有人可能会争辩说,使用触发器,NOT NULL 约束是多余的——触发器将确保这些值无论如何都不是 NULL。在这方面我有点不清楚什么是最佳实践。但我不希望这些列永远为 NULL,并且约束使这一点显而易见。
3)我现在的触发器是:
ALTER TRIGGER [dbo].[TR_dim_InjuryType_Audit]
ON [dbo].[dim_InjuryType]
AFTER INSERT, UPDATE
AS
SET NOCOUNT ON
DECLARE @CurrentUserID INT;
SELECT @CurrentUserID = u.UserID
FROM [dbo].[dim_Users] U
WHERE u.[Username] = dbo.udfUserName()
UPDATE T
SET DateModified = GETDATE(),
WhoModifiedID = @CurrentUserID
FROM INSERTED E
JOIN [dbo].[dim_InjuryType] T ON e.[InjuryTypeID] = t.[InjuryTypeID]
4)顺便说一句, dbo.udfUserName() 仅仅是:
-- =============================================
-- Author: Scott Bass
-- Create date: 04JUL2014
-- Description: Return userid without the domain
-- =============================================
ALTER FUNCTION [dbo].[udfUserName]
(
)
RETURNS varchar(20)
AS
BEGIN
-- Declare the return variable here
DECLARE @UserName varchar(20)
-- Add the T-SQL statements to compute the return value here
SELECT @UserName = substring(suser_sname(),charindex('\',suser_sname())+1,99)
-- Return the result of the function
RETURN @UserName
END
5)感谢提示:不在 SSMS 中使用 EDIT TOP 200 ROWS
这是我想要的。对改进/最佳实践的进一步评论非常受欢迎,另外将帮助那些以后找到这个线程的人。
我的 Access 前端很烦人,这可能与触发器有关,但实际上是单独帖子的单独主题。但是,为了完整性,我包含此链接,以防有人感兴趣: http ://www.utteraccess.com/forum/User-Edited-Record-Sav-t2019558.html