[英]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.