2017-03-06 165 views
0

我正在创建我的第一个SQL Server触发器,并且在插入另一个表后查找INSERT到“历史记录”表中。我认为我编写了大部分代码,但似乎无法完成语法。当前格式指出“HistoryColumnName”和“HistoryNewValue”无效。我已经尝试了JOIN到变量表@HistoryRecord,但它没有真正意义,因为它们是独立的。下面SQL Server:为审计/历史记录创建触发器表

代码:

CREATE TRIGGER CreateHardwareAssetHistoryRecord 
ON HardwareAsset 
AFTER INSERT AS 

DECLARE 
@HardwareAssetID UNIQUEIDENTIFIER, 
@HardwareAssetTitle VARCHAR(256), 
@HardwareAssetSerialNumber VARCHAR(256) 
SET @HardwareAssetID = (SELECT HardwareAssetID FROM inserted) 
SET @HardwareAssetTitle = (SELECT HardwareAssetTitle FROM inserted) 
SET @HardwareAssetSerialNumber = (SELECT HardwareAssetSerialNumber FROM inserted) 

DECLARE @HistoryRecord TABLE (HistoryColumnName VARCHAR(256) NOT NULL, HistoryNewValue VARCHAR(256) NOT NULL) 
INSERT @HistoryRecord(HistoryColumnName,HistoryNewValue) VALUES('Asset Name', @HardwareAssetTitle) 
INSERT @HistoryRecord(HistoryColumnName,HistoryNewValue) VALUES('Serial Number', @HardwareAssetSerialNumber) 

BEGIN 

WHILE EXISTS(SELECT HistoryColumnName,HistoryNewValue FROM @HistoryRecord) 

INSERT INTO HardwareAssetHistory 
(HardwareAssetHistoryChangeTypeID, HardwareAssetHistoryUpdatedByID, HardwareAssetHistoryColumnName, HardwareAssetHistoryOldValue, HardwareAssetHistoryNewValue, HardwareAssetHistoryHardwareAssetID) 
SELECT '1', HardwareAssetCreatedByID, HistoryColumnName, '', HistoryNewValue, HardwareAssetID 
FROM HardwareAsset 
WHERE HardwareAssetID = @HardwareAssetID 

END 
GO 

任何建议或帮助,将不胜感激。

注意:因为我们使用的是由@ nick.mcdermaid如指出,下面就不会当有多个行

+1

您可能希望使用时态表。 https://www.google.com.au/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0ahUKEwjKt5OGg8PSAhUJzbwKHQf5B_8QFggZMAA&url=https%3A%2F%2Fmsdn.microsoft.com%2Fen-us%2Flibrary%2Fdn935015。 aspx&usg = AFQjCNG2VZa8v6Y_rCW-rWB_2VTUW1-Idw&sig2 = fouMv9WhcDjahToxkDiWoQ&bvm = bv.148747831,d.dGc&cad = rja如果您刚刚开始学习SQL,请允许我向您保证避免使用触发器。虽然你可以学习构建一个重要的概念,但在实践中,它们通常不是一个好主意。 –

+4

首先要学习的是由_every_首次触发作者所犯的错误。那就是每个批次触发一次,而不是每行一次。换句话说,'inserted'表可以有多行,这意味着在这种情况下'SET @HardwareAssetID =(SELECT HardwareAssetID FROM FROM inserted)'语句会引发错误 –

+1

表'HardwareAsset'是否有一个名为' HistoryColumnName'?我猜不会。这是你错误的直接原因,但这只是一个更大问题的症状,你需要了解其他一些概念 –

回答

1

您可以通过选择其他值做到这一点没有你的临时表且参考原来HardwareAsset表变量。

CREATE TRIGGER CreateHardwareAssetHistoryRecord ON HardwareAsset INSERT AS BEGIN DECLARE @HardwareAssetID UNIQUEIDENTIFIER, @HardwareAssetTitle VARCHAR(256), @HardwareAssetSerialNumber VARCHAR(256), @HardwareAssetCreatedByID INT --change什么是后这

SELECT @HardwareAssetID = HardwareAssetID, @HardwareAssetTitle = HardwareAssetTitle 
      , @HardwareAssetSerialNumber = HardwareAssetSerialNumber 
      , @HardwareAssetCreatedByID = HardwareAssetCreatedByID FROM inserted 

    INSERT INTO HardwareAssetHistory(HardwareAssetHistoryChangeTypeID 
         , HardwareAssetHistoryUpdatedByID, HardwareAssetHistoryColumnName 
         , HardwareAssetHistoryOldValue, HardwareAssetHistoryNewValue 
         , HardwareAssetHistoryHardwareAssetID) 
    VALUES ('1', @HardwareAssetCreatedByID, 'Asset Name', '', @HardwareAssetTitle 
                , @HardwareAssetID), 
     ('1', @HardwareAssetCreatedByID, 'Serial Number', '', @HardwareAssetSerialNumber 
                , @HardwareAssetID) 
END 
GO 

01数据类型

UPDATE:这将多行以及工作:

CREATE TRIGGER CreateHardwareAssetHistoryRecord 
    ON HardwareAsset 
AFTER INSERT AS 
BEGIN 

    DECLARE @insertedTemp AS TABLE (HardwareAssetID UNIQUEIDENTIFIER, HardwareAssetTitle VARCHAR(256), HardwareAssetSerialNumber VARCHAR(256), HardwareAssetCreatedByID INT) 

    INSERT INTO @insertedTemp(HardwareAssetID, HardwareAssetTitle, HardwareAssetSerialNumber, HardwareAssetCreatedByID) 
    SELECT HardwareAssetID, HardwareAssetTitle, HardwareAssetSerialNumber, HardwareAssetCreatedByID FROM inserted 

    INSERT INTO HardwareAssetHistory(HardwareAssetHistoryChangeTypeID 
         , HardwareAssetHistoryUpdatedByID, HardwareAssetHistoryColumnName 
         , HardwareAssetHistoryOldValue, HardwareAssetHistoryNewValue 
         , HardwareAssetHistoryHardwareAssetID)  
    SELECT '1', HardwareAssetCreatedByID, 'Asset Name', '', HardwareAssetTitle, @HardwareAssetID 
    FROM @insertedTemp 

UNION  

    SELECT '1', HardwareAssetCreatedByID, 'Serial Number', '', HardwareAssetSerialNumber, HardwareAssetID 
    FROM @insertedTemp  
END 
GO 
+2

当'inserted'具有多条记录时,这不会按预期运行。如果您不需要任何变量,只需执行插入/选择 –

+1

@ Nick.McDermaid好点匹配,新解决方案可以处理多行数据,它将起作用。 – TheVillageIdiot

+1

我不知道'@ insertedTemp'在这里甚至是必要的,但是我不太明白逻辑 –