簡體   English   中英

SQL觸發器在刪除過程中只返回一條記錄

[英]SQL trigger only returning one record during a delete

下面是我為 SQL 數據庫中的表創建的觸發器(我們正在運行 SQL Server 2008)。 我們將批量進行更新、插入和刪除,因此我們創建了這個觸發器和一個“存儲”表 (TransactionLog) 來捕獲所有活動。 到目前為止,這個觸發器非常適合插入和更新。 所有記錄都以所有適當的值出現在“存儲”表中。

但是,當我們嘗試刪除多於一條記錄的任何內容時,就會出現問題。 此觸發器捕獲並發送到“存儲”表的唯一記錄是最后刪除的記錄。 所有其他人都迷路了。

CREATE TRIGGER [dbo].[trg_Agent_ALL] 
ON [dbo].[Agent]

FOR INSERT, UPDATE, DELETE
AS
BEGIN

--TransactionLog variables
DECLARE @tableName char(25) = 'Agent'
DECLARE @transDate datetime 
DECLARE @lastChangeOperator char(6) 
DECLARE @tableString char(255)
DECLARE @action char(1) = 'I'
DECLARE @userId char(25)

--Trigger table variables
DECLARE @sNumber char(10)
DECLARE @controlId char(3)
DECLARE @entityType char(1)
DECLARE @firstName nvarchar(50)
DECLARE @lastName nvarchar(50)
DECLARE @suffix nvarchar(10)
DECLARE @corpName nvarchar(100)


IF EXISTS (SELECT * FROM deleted)
    BEGIN
        SET @action = 
            CASE    
                WHEN EXISTS (SELECT * FROM inserted) THEN 'U'
                ELSE 'D'
            END
    END

IF @action = 'D'
    BEGIN 
        SELECT @sNumber = sNumber, @lastChangeOperator = LastChangeOperator, @transDate = LastChangeDate, @entityType = EntityType, 
        @firstName = FirstName, @lastName = LastName, @suffix = NameSuffix, @corpName = CorporateName, @controlId = ControlId
        FROM deleted

        IF @firstName IS NULL SET @firstName = 'NULL'
        IF @lastName IS NULL SET @lastName = 'NULL'
        IF @suffix IS NULL SET @suffix = 'NULL'
        IF @corpName IS NULL SET @corpName = 'NULL'
        IF @controlId IS NULL SET @controlId = 'NULL'

        SET @tableString = 'sNum:' + @sNumber + ' ' + 'EntType:' + @entityType + ' ' + 'Fname:' + @firstName + ' ' + 'Lname:' + @lastname + ' ' + 'suf:' + @suffix +
            ' ' + 'crpName:' + @corpName + ' ' + 'crlId:' + @controlId
    END
ELSE
    BEGIN
        SELECT @sNumber = SymetraNumber, @lastChangeOperator = LastChangeOperator, @transDate = LastChangeDate, @entityType = EntityType, 
        @firstName = FirstName, @lastName = LastName, @suffix = NameSuffix, @corpName = CorporateName, @controlId = ControlId
        FROM inserted

        IF @firstName IS NULL SET @firstName = 'NULL'
        IF @lastName IS NULL SET @lastName = 'NULL'
        IF @suffix IS NULL SET @suffix = 'NULL'
        IF @corpName IS NULL SET @corpName = 'NULL'
        IF @controlId IS NULL SET @controlId = 'NULL'

        SET @tableString = 'sNum:' + @sNumber + ' ' + 'EntType:' + @entityType + ' ' + 'Fname:' + @firstName + ' ' + 'Lname:' + @lastname + ' ' + 'suf:' + @suffix +
            ' ' + 'crpName:' + @corpName + 'crlId:' + @controlId
    END

INSERT INTO TransactionLog (TransactionDate, Operator, TableName, Action, TableString, UserId)
VALUES (@transDate, 'Op', @tableName, @action, @tableString, @lastChangeOperator)

END

根據下面的評論,我更改了刪除部分中的 SQL 代碼。 硬編碼值似乎有效,但是我將它們放在那里的主要原因只是為了顯示這些是我需要為那些特定列提供的值。 我在上面的代碼中使用這些值設置了變量(請參閱 DECLARE 語句)。 但是,這給了我以下錯誤消息:

 Conversion failed when converting the varchar value 'P' to data type int.

此錯誤來自內部 SELECT 語句中的 EntityType 屬性。 讓我感到困惑的是,該列的數據類型設置為 char(1),而 TableString 列(連接值的目標)的數據類型為 nvarchar(255)。 不知道“int”來自哪里......

IF @action = 'D'
    BEGIN   
        INSERT INTO TransactionLog (TransactionDate, Operator, TableName, Action, TableString, UserId)
        SELECT LastChangeDate, 'Op', 'Agent', 'D', 
        (SELECT CAST(CAST(sNumber as nvarchar) + ' ' + EntityType + ' ' + ISNULL(FirstName, ' ') + ' ' + ISNULL(LastName, ' ') + ' ' + ISNULL(NameSuffix, ' ') + ' ' + 
                ISNULL(CorporateName, ' ' ) + ' ' + ISNULL(CAST(ControlId as nvarchar), ' ') AS nvarchar) as TableString
        FROM deleted), LastChangeOperator
        FROM deleted
    END
ELSE

編輯

通過將 sNumber 和 controlId 字段轉換為 nvarchar,我能夠跳過我之前的錯誤消息。 現在,但是我收到下面發布的不同錯誤消息:

 Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.

最終編輯

像這樣更改子查詢允許我將多條已刪除的記錄返回到審計表中,因為我一次只請求一條記錄。

IF @action = 'D'
    BEGIN 
        INSERT INTO TransactionLog (TransactionDate, Operator, TableName, Action, TableString, UserId)
            SELECT LastChangeDate, 'Op', 'Agent', 'D', 
            CAST('SymNum:' + CAST(SymetraNumber as nvarchar(30)) + ' entType:' + EntityType + ' Fname:' + ISNULL(FirstName, 'NULL') + ' Lname:' + ISNULL(LastName, 'NULL') +
             ' suff:' + ISNULL(NameSuffix, 'NULL') + ' corpName:' + ISNULL(CorporateName, 'NULL' ) + ' ctrlId:' + ISNULL(CAST(ControlId as nvarchar(30)), 'NULL') AS nvarchar(30)) as TableString
            , LastChangeOperator
        FROM deleted
    END
ELSE 

select @sNumber = sNumber, ..語法將為每一行覆蓋一次變量,因此您最終只會得到最后一行的值。

然后你還要insert into ... values (...) ,它只能插入一行。

您應該嘗試以以下形式重寫它:

insert into TransactionLog ( ... )
select sNumber, ... from deleted

您可以使用ISNULL(lastname, 'NULL')代替 if 語句。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM