【发布时间】:2014-08-10 22:47:11
【问题描述】:
这是我的情况。我正在使用 ASP.NET MVC 5。
我的要求是将记录的添加/更新/删除操作跟踪到历史表中。
此示例有 2 个表 A 和 B 用于原始记录,另一个表 AHistories 和 BHistories 用于保存历史记录。存在一对多关系,一个 A 和多个 B。
我使用触发器来实现这一点。我被与外键相关的事情困住了。当我在触发器中将记录插入历史记录表时,我想使用指向历史记录表中的 ID 而不是原始表的外键保存记录。
这就是我在触发器中所做的。
CREATE TRIGGER A_History_Trigger ON A FOR INSERT, UPDATE, DELETE AS
SET NOCOUNT ON;
DECLARE @AHistoryID INT
IF EXISTS (SELECT * FROM Inserted)
BEGIN
DECLARE @HistoryType NVARCHAR(6)
IF EXISTS (SELECT * FROM Deleted)
SET @HistoryType = 'update'
ELSE
SET @HistoryType = 'add'
/* Save record from table A into AHistories table */
INSERT INTO AHistories (HistoryID, Area, ModifiedDate, HistoryType)
SELECT ID, Area, CURRENT_TIMESTAMP, @HistoryType
FROM Inserted
/* Save updated record from table B into BHistories table */
IF @HistoryType = 'update'
INSERT INTO BHistories (HistoryID, AHistoryID, Name, ModifiedDate, HistoryType)
SELECT ID, SCOPE_IDENTITY(), Name, CURRENT_TIMESTAMP, @HistoryType
FROM B
WHERE AID = (SELECT ID FROM Inserted)
END
ELSE /* Delete */
BEGIN
INSERT INTO AHistories (HistoryID, Area, ModifiedDate, HistoryType)
SELECT ID, Area, CURRENT_TIMESTAMP, 'delete' FROM Deleted
DECLARE @AID INT
SET @AID = (SELECT ID FROM Deleted)
SET @AID = SCOPE_IDENTITY()
/* B */
INSERT INTO BHistories (HistoryID, AHistoryID, Name, ModifiedDate, HistoryType)
SELECT ID, @AHistoryID, Name, CURRENT_TIMESTAMP, 'delete'
FROM B
WHERE AID = @AID
DELETE FROM B WHERE AID = @AID
END
在表 B 的触发器中,
CREATE TRIGGER B_History_Trigger ON B FOR INSERT AS
SET NOCOUNT ON;
DECLARE @AHistoryID INT
/* Is this safe? */
SET @AHistoryID = (SELECT TOP 1 ID FROM AHistories WHERE HistoryID = (SELECT TOP 1 AID FROM Inserted) ORDER BY ID DESC)
INSERT INTO BHistories (HistoryID, Name, AHistoryID, ModifiedDate, HistoryType)
SELECT ID, Name, @AHistoryID, CURRENT_TIMESTAMP, 'add' FROM Inserted
在 B 的触发器中,通过在那里执行 SELECT 获得正确的 AHistoryID 是否安全?在生产中,我担心是否存在多个用户同时执行操作时触发器会选择错误的 AHistoryID 的情况。这是可接受的方法吗?
感谢任何cmets。
【问题讨论】:
-
如果你可以让多个人访问一个表,假设它会。无论如何,你的 id 应该仍然指向“原始”的——如果你改变它们,它会破坏历史(你怎么知道它来自哪个 id?)。我什至可能没有这些表的唯一 ID - 通常您不关心更新/删除特定行,您关心整体历史记录。因此,您正在运行
SELECT语句,这些语句要么获取所有行(带有它们的时间戳,这可能是唯一的......),要么是更复杂的东西,其中 id 无论如何都无关紧要(例如,最近的更改)。 -
在我的历史表中,我有唯一的 ID 和 HistoryID 字段,其中 HistoryID 是原始记录的 ID。当我更新 A 时,我想知道 A 记录在该更新时有哪些 B 记录。这样,我总能看到它指向的 Bs。我错过了一点吗?
-
您通常会使用审计时间戳重新构建它。您还应该能够使用它来获取审核唯一 ID。如果您像这样存储派生的 fks,您希望将它们存储在 addition 到原始 fks 中。您的跳汰机也不适合多排使用...
标签: sql sql-server database triggers