我做了很多环顾四周,还没找到我想要的东西。很抱歉,如果这是一个重复的问题,我没有看到符合我需求的问题。
我有一个应用程序表[UserInRoles]
,其中包含2列[UserID]
和[RoleID]
。当用户切换到其他角色时,应用程序使用Inserts for new Users和Updates管理此表。
我有一个历史记录表[UserRoleHistory]有4列[UserID]
,[RoleID_New]
,[RoleID_Old]
,[DateOfChange]
我需要弄清楚的是如何创建一个触发器,每次[UserRoleHistory]
更改时都会在[UserInRoles].[RoleId]
中插入一个新行。我希望将旧的RoleId存储在列[RoleId_Old]
中,并将新的RoleId存储在列[RoleId_New]
中。此外,[UserId]
需要存储并GETDATE()
用于向[DateOfChange]
增加值
此外,(这是可能的)我希望触发器在对应用程序表[UserInRoles]
进行插入时注意并将数据[UserId], [RoleId],GETDATE()
保存到历史记录中表格为[UserId], [RoleId_New] , GETDATE()
并保留[RoleId_Old] as a null
值。
我对触发器很新,不知道如何继续。我没有权限删除触发器,如果我搞砸了所以我还没有尝试创建一个。只想先得到一些专家意见。提前感谢所有花时间阅读和回答/评论的人。
**** **** EDIT 我已经使用了你的建议,这就是我最终提出的建议。这个触发器有一些我最初要求的信息,但在使用它之后发现历史表中我想要的信息很容易找到,我按照我认为合适的方式添加了它。
CREATE TRIGGER [dbo].[UserInRoles_Insert_Delete_Update] ON [dbo].[UsersInRoles]
AFTER INSERT,DELETE,UPDATE
AS
IF (SELECT COUNT(*) FROM inserted) > 0
BEGIN
IF (SELECT COUNT(*) FROM deleted) > 0
BEGIN
-- update!
INSERT INTO [dbo].[UserRole_History](WinNTLogin,UserID,RoleID_Old,RoleID_New,RoleName,DateOfChange,Operation)
SELECT (select distinct[LoweredUserName] from [dbo].[Users]
where (inserted.UserId = Users.UserId) or (deleted.UserId = Users.UserId))
,CASE
WHEN inserted.UserID IS NOT NULL THEN inserted.UserID
ELSE deleted.UserID
END
,deleted.RoleID
,inserted.RoleID
,(select distinct[RoleName] from [dbo].[Roles]
where (inserted.RoleId = Roles.RoleId) or (deleted.RoleId = Roles.RoleId))
,GETDATE()
,'U'
FROM inserted
FULL JOIN deleted
ON inserted.UserID = deleted.UserID
END
ELSE
BEGIN
-- insert!
INSERT INTO [dbo].[UserRole_History](WinNTLogin,UserID,RoleID_Old,RoleID_New,RoleName,DateOfChange,Operation)
SELECT (select distinct[LoweredUserName] from [dbo].[Users]
where (inserted.UserId = Users.UserId) or (deleted.UserId = Users.UserId))
,CASE
WHEN inserted.UserID IS NOT NULL THEN inserted.UserID
ELSE deleted.UserID
END
,deleted.RoleID
,inserted.RoleID
,(select distinct[RoleName] from [dbo].[Roles]
where (inserted.RoleId = Roles.RoleId) or (deleted.RoleId = Roles.RoleId))
,GETDATE()
,'I'
FROM inserted
FULL JOIN deleted
ON inserted.UserID = deleted.UserID
END
END
ELSE
BEGIN
-- delete!
INSERT INTO [dbo].[UserRole_History](WinNTLogin,UserID,RoleID_Old,RoleID_New,RoleName,DateOfChange,Operation)
SELECT (select distinct[LoweredUserName] from [dbo].[Users]
where (inserted.UserId = Users.UserId) or (deleted.UserId = Users.UserId))
,CASE
WHEN inserted.UserID IS NOT NULL THEN inserted.UserID
ELSE deleted.UserID
END
,deleted.RoleID
,inserted.RoleID
,(select distinct[RoleName] from [dbo].[Roles]
where (inserted.RoleId = Roles.RoleId) or (deleted.RoleId = Roles.RoleId))
,GETDATE()
,'D'
FROM inserted
FULL JOIN deleted
ON inserted.UserID = deleted.UserID
END
GO
答案 0 :(得分:1)
MSDN创建触发器文档(https://msdn.microsoft.com/en-GB/library/ms189799.aspx)在最后有一些方便的示例。我以无耻的方式复制/粘贴下面的第一个作为例子:
IF OBJECT_ID ('Sales.reminder2','TR') IS NOT NULL
DROP TRIGGER Sales.reminder2;
GO
CREATE TRIGGER reminder2
ON Sales.Customer
AFTER INSERT, UPDATE, DELETE
AS
EXEC msdb.dbo.sp_send_dbmail
@profile_name = 'AdventureWorks2012 Administrator',
@recipients = 'danw@Adventure-Works.com',
@body = 'Don''t forget to print a report for the sales force.',
@subject = 'Reminder';
GO
这与您相关,因为它显示
如果您需要专门比较某个值以确保该值已更改,那么之前的帖子类似于here。 Essentialy你写
INSTEAD OF INSERT
代替
AFTER INSERT
然后你可以根据需要做任何条件逻辑或CRUD操作。
最后,因为您可以在触发器中弹出一个过程(如上所示),您可以为您将创建的任何触发器添加一些额外的复杂性,从而抽象掉本身在触发器本身中的任何逻辑。
答案 1 :(得分:1)
注意:我使用了您所使用的相同表名,因此不要使用实际表格对数据库运行此名称,因为我删除了它们。
试一试。这适用于任何更新,插入或删除。如果更改了UserID(可能不应该发生),那么它看起来就像是插入了新RoleID的新UserId。如果您还有其他需要,请告诉我。
--If the tables exist, delete them
IF OBJECT_ID('UserInRoles') IS NOT NULL
DROP TABLE UserInRoles;
IF OBJECT_ID('UserRoleHistory') IS NOT NULL
DROP TABLE UserRoleHistory;
CREATE TABLE UserInRoles
(
UserID INT PRIMARY KEY,
RoleID INT
);
GO
CREATE TABLE UserRoleHistory
(
UserID INT,
RoleID_Old INT,
RoleID_New INT,
DateOfChange DATETIME
);
GO
CREATE TRIGGER trg_History ON UserInRoles
AFTER INSERT,DELETE,UPDATE
AS
INSERT INTO UserRoleHistory(UserID,RoleID_Old,RoleID_New,DateOfChange)
SELECT CASE
WHEN inserted.UserID IS NOT NULL THEN inserted.UserID
ELSE deleted.UserID
END,
deleted.RoleID,
inserted.RoleID,
GETDATE()
FROM inserted
FULL JOIN deleted
ON inserted.UserID = deleted.UserID
GO
INSERT INTO UserInRoles
VALUES (1,1);
INSERT INTO UserInRoles
VALUES (2,1);
INSERT INTO UserInRoles
VALUES (3,2);
GO
UPDATE UserInRoles
SET RoleID = 111
WHERE RoleID = 1;
GO
UPDATE UserInRoles
SET RoleID = 222
WHERE RoleID = 2;
GO
DELETE
FROM UserInRoles
WHERE UserID >= 1
GO
SELECT *
FROM UserRoleHistory
ORDER BY DateOfChange
结果:
UserID RoleID_Old RoleID_New DateOfChange
----------- ----------- ----------- -----------------------
1 NULL 1 2015-03-20 13:06:37.010
2 NULL 1 2015-03-20 13:06:37.010
3 NULL 2 2015-03-20 13:06:37.010
2 1 111 2015-03-20 13:06:37.047
1 1 111 2015-03-20 13:06:37.047
3 2 222 2015-03-20 13:06:37.050
3 222 NULL 2015-03-20 13:06:37.063
2 111 NULL 2015-03-20 13:06:37.063