简体   繁体   English

SQL触发器在删除过程中只返回一条记录

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

Below is a trigger I've created for a table in a SQL database (We are running SQL Server 2008).下面是我为 SQL 数据库中的表创建的触发器(我们正在运行 SQL Server 2008)。 We are going to be doing updates, inserts, and deletes in bulk so we created this trigger and a "storage" table (TransactionLog) to capture all the activity.我们将批量进行更新、插入和删除,因此我们创建了这个触发器和一个“存储”表 (TransactionLog) 来捕获所有活动。 So far, this trigger works perfectly for inserts and updates.到目前为止,这个触发器非常适合插入和更新。 All the records wind up in the "storage" table with all appropriate values.所有记录都以所有适当的值出现在“存储”表中。

However, the problem occurs when we try to delete anything more than one record.但是,当我们尝试删除多于一条记录的任何内容时,就会出现问题。 The only record this trigger captures and sends to the "storage" table is the last record deleted.此触发器捕获并发送到“存储”表的唯一记录是最后删除的记录。 All others get lost.所有其他人都迷路了。

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

Based on the comments below I've altered the SQL code in the delete section.根据下面的评论,我更改了删除部分中的 SQL 代码。 The hard-coded values seem to be working, however the main reason I placed them in there just to show those are the values I need for those specific columns.硬编码值似乎有效,但是我将它们放在那里的主要原因只是为了显示这些是我需要为那些特定列提供的值。 I have variables set with these values in the code above (see the DECLARE statements).我在上面的代码中使用这些值设置了变量(请参阅 DECLARE 语句)。 This, however, is giving me the following error message:但是,这给了我以下错误消息:

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

This error is coming off of the EntityType attribute in the inner SELECT statement.此错误来自内部 SELECT 语句中的 EntityType 属性。 What confuses me is that this column has a data type set to char(1), and the TableString column (the destination of the concatenated values) has a data type of nvarchar(255).让我感到困惑的是,该列的数据类型设置为 char(1),而 TableString 列(连接值的目标)的数据类型为 nvarchar(255)。 No clue where the "int" is coming from...不知道“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

EDIT编辑

By casting the sNumber and controlId fields to nvarchar I was able to move past my previous error message.通过将 sNumber 和 controlId 字段转换为 nvarchar,我能够跳过我之前的错误消息。 Right now, however I am receiving a different error message posted below:现在,但是我收到下面发布的不同错误消息:

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

FINAL EDIT最终编辑

Altering the subquery like so allowed me to return multiple deleted records into the Audit table as I was only requesting one record at a time.像这样更改子查询允许我将多条已删除的记录返回到审计表中,因为我一次只请求一条记录。

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 

That select @sNumber = sNumber, .. syntax will overwrite the variables once for each row, so you end up only with the last row's values. select @sNumber = sNumber, ..语法将为每一行覆盖一次变量,因此您最终只会得到最后一行的值。

And then you also do an insert into ... values (...) , which can only insert one row.然后你还要insert into ... values (...) ,它只能插入一行。

You should try to rewrite it in the form:您应该尝试以以下形式重写它:

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

You can use ISNULL(lastname, 'NULL') instead of your if-statements.您可以使用ISNULL(lastname, 'NULL')代替 if 语句。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM