从触发器中的多行创建一条记录

时间:2017-08-30 18:27:23

标签: sql-server tsql database-trigger

我有一个触发器,在插入记录时触发。应用程序修改员工的银行记录,但每次创建四条记录,无论是否只更新或插入一个字段

例如,您更新员工的帐号。应用程序将在审计表中插入四行,包括记录类型帐号,帐户类型,银行和分支。每个插入的行都有一个旧值和一个新值。

数据看起来像这样:

Auditfieldid, recordtype, old value, new value
----------------------------------------------
1, account number, 99, 88
1, account type, C, A
1, bank, BOA, Regions
1, branch, Cedar Bluff, Clinton

我希望触发器遍历插入的记录,但在临时表中构建一行包含:

Auditfieldid, AccountNoOldvalue, AccountNoNewValue, AccountTypeOldValue,
  AccountTypeNewValue, BankOldValue, BankNewValue, BranchOldValue, BranchNewValue
---------------------------------------------------------------------------------
1, 99, 88, C, A, BOA, Regions, Cedar Bluff, Clinton

然后,上面的数据会在HTML电子邮件中显示。如果我不做上述操作,则会收到4封电子邮件作为通知发送,我只想要一封包含所有值的电子邮件。

这是我到目前为止所做的工作,但会生成4封电子邮件:

USE [SageStaging]
GO

/****** Object:  Trigger [MASSMART].[Vip_BankChange_Email]    Script Date: 2017-08-07 11:49:06 PM ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

--USE [SageStaging]
--GO

/****** Object:  Trigger [MASSMART].[Vip_BankChange_Email]    Script Date: 2017-07-12 08:36:41 AM ******/
--SET ANSI_NULLS ON
--GO

--SET QUOTED_IDENTIFIER ON
--GO
--/------ 

ALTER TRIGGER [MASSMART].[Vip_BankChange_Email] 
ON [MASSMART].[MM_BankAudit] 
AFTER UPDATE
AS
 SET NOCOUNT ON;

DECLARE @AUDITFIELDID NVARCHAR(500)
DECLARE @EFFECTIVEDATE VARCHAR(500)
DECLARE @VIPUSERNAME VARCHAR(500)
DECLARE @SOURCECODE VARCHAR(500)
DECLARE @ACTIONSDESCRIPTION VARCHAR(500)
DECLARE @FIELDNAME VARCHAR(500)
DECLARE @TABLEFRIENDLYNAME VARCHAR(500)
DECLARE @OLDVALUE NVARCHAR(500)
DECLARE @AUDITVALUE NVARCHAR(500)
DEClARE @COMPANYRULE NVARCHAR(MAX)
DECLARE @Mail_Profile_Name VARCHAR(100)
DECLARE @SENT VARCHAR(10)
SET @Mail_Profile_Name = 'Sendmail'
DECLARE @MessageBody VARCHAR(MAX)
DECLARE @MailSubject NVARCHAR(500)
DECLARE @@CC VARCHAR(50)
DECLARE @@Sendto NVARCHAR(100)
DECLARE @COMPANYRULEID NVARCHAR(100)
DECLARE @NUMKEY NVARCHAR(100)


DECLARE Email_cursor CURSOR FOR

SELECT AUDITFIELDID, 
       companyruleid, 
       effectivedate, 
       VIPUserName, 
       SourceCode, 
       ActionsDescription, 
       FieldName, 
       OldValue, 
       AuditValue, 
       CompanyRule, 
       Sent, 
       numkey  
  FROM inserted


OPEN Email_cursor;

FETCH NEXT FROM Email_cursor INTO @AUDITFIELDID, @companyruleid, @effectivedate, @VIPUserName, @SourceCode, @ActionsDescription, @FieldName, @OldValue, @AuditValue, @CompanyRule, @sent, @numkey 


WHILE @@FETCH_STATUS = 0
BEGIN

SET @MailSubject = 'Banking Details Change Notification for Employee' + ' ' + @SOURCECODE
SET @MessageBody = '<html>
<head>
  <meta content="text/html; charset=ISO-8859-1"
 http-equiv="content-type">
  <title></title>
</head>
<body>
<br>
The following bank details have been changed: 
<br>
<br>
 Date Changed:    ' + @EFFECTIVEDATE + '<br>' +
' Username:    ' + @VIPUSERNAME + '<br>' +
' Employee Details:    ' + @SOURCECODE + '<br>' +
' Action:    ' + @ACTIONSDESCRIPTION + '<br>' +
' Field:    ' + @FIELDNAME + '<br>' +
' Old Value:    ' + @OLDVALUE + '<br>' +
' New Value:    ' + @AUDITVALUE + '<br>' +
' Company:    ' + @COMPANYRULE + '<br>
<br>
<b>
Please do not respond to this email. If you have any questions regarding this email, please
contact your payroll administrator <br>
<br>
<br>
</body>
</html>'


-- Massmart Employers (Exec)
IF @COMPANYRULEID IN (36)
BEGIN
SET @@Sendto = 'john.doe@gmail.com'
END

-- Massmart Employers

IF @COMPANYRULEID IN (40,1,35,44)
BEGIN
SET @@Sendto = 'john.doe@gmail.com'
END



-- Cambridge Employers
IF @COMPANYRULEID IN (104,105,51,52,54,55,56,57)
BEGIN
SET @@Sendto = 'john.doe@gmail.com'
END

-- Builders Employers

IF @COMPANYRULEID IN (101,102,12,13,14,15,16,17,18,19,20,98)
BEGIN
SET @@Sendto = 'john.doe@gmail.com'
END

-- MDD Employers

IF @COMPANYRULEID IN (106,107,108,2,21,26,27,29,3,30,31,33,34,4,5,6,72,80,83,94,86,9,95,96,97,99)
BEGIN
SET @@Sendto = 'john.doe@gmail.com'
END

-- Unison

IF @COMPANYRULEID IN (37,39)
BEGIN
SET @@Sendto = 'Annie.mahadasen@massmart.co.za;Candice.mcanda@massmart.co.za;dknoetz@massmart.co.za'
END

-- FruitSpot

IF @COMPANYRULEID IN (46)
BEGIN
SET @@Sendto = 'john.doe@gmail.com'
END

-- Masscash

IF @COMPANYRULEID IN (103,58,60,63,64,65,66,68,69,79,81,85,89,90,91,92,93,94)
BEGIN
SET @@Sendto = 'john.doe@gmail.com'
END

-- Makro Employers

IF @COMPANYRULEID IN (70,47,48,50,78)
BEGIN
SET @@Sendto = 'john.doe@gmail.com'
END




EXEC msdb.dbo.sp_send_dbmail
@profile_name = @Mail_Profile_Name,
@recipients = @@Sendto,
@body = @MessageBody,
@subject = @MailSubject,
@body_format = 'HTML'




FETCH NEXT FROM Email_cursor INTO @AUDITFIELDID, @COMPANYRULEID, @effectivedate, @VIPUserName, @SourceCode, @ActionsDescription, @FieldName, @OldValue, @AuditValue, @CompanyRule, @sent 

END


CLOSE Email_cursor
DEALLOCATE Email_cursor

1 个答案:

答案 0 :(得分:0)

根据数据的插入方式,触发器只能在Inserted中的四行中触发一次,或者每次在Inserted中一行触发四次。

第一种情况,触发器仅触发一次

这是一个简单的例子,你可以像下面这样使用SELECT来缩小一行中的所有值:

select ID,
  (select OldValue from Inserted
   where recordtype='account number' and ID=Temp.ID) as AccountNoOldvalue,
  (select NewValue from Inserted
   where recordtype='account number' and ID=Temp.ID) as AccountNoNewValue,
  (select OldValue from Inserted
   where recordtype='account type' and ID=Temp.ID) as AccountTypeOldValue,
  (select NewValue from Inserted
   where recordtype='account type' and ID=Temp.ID) as AccountTypeNewValue,
  (select OldValue from Inserted
   where recordtype='bank' and ID=Temp.ID) as BankOldValue,
  (select NewValue from Inserted
   where recordtype='bank' and ID=Temp.ID) as BankNewValue,
  (select OldValue from Inserted
   where recordtype='branch' and ID=Temp.ID) as BranchOldValue,
  (select NewValue from Inserted
   where recordtype='branch' and ID=Temp.ID) as BranchNewValue
from Inserted as Temp
group by ID

第二种情况,触发器为每条记录触发

在这种情况下,如问题评论中所述,您无法在触发器内同时获取所有值。我会添加另一个审计表到数据库,从触发器填充它,当为给定的ID填充四种类型的更改,然后从新表的第二个触发器发送电子邮件:

create table AuditCondensed (
  ID int,
  AccountNoOldValue varchar(100),
  AccountNoNewValue varchar(100),
  AccountTypeOldValue varchar(100),
  AccountTypeNewValue varchar(100),
  BankOldValue varchar(100),
  BankNewValue varchar(100),
  BranchOldValue varchar(100),
  BranchNewValue varchar(100)
)
go

create trigger trFillAuditCondensed on YourCurrentAuditTable
after insert as
  declare @ID int, @RecordType char(25)

  select @ID=ID, @RecordType=RecordType from Inserted

  if not exists(select * from AuditCondensed where ID=@ID)
    insert into AuditCondensed (ID) select ID from Inserted

  if @RecordType='account number'
    update AuditCondensed set AccountNoOldvalue=OldValue,
      AccountNoNewValue=NewValue
    from AuditCondensed
    join Inserted on Inserted.ID=AuditCondensed.ID
  if @RecordType='account type'
    update AuditCondensed set AccountTypeOldValue=OldValue,
      AccountTypeNewValue=NewValue
    from AuditCondensed
    join Inserted on Inserted.ID=AuditCondensed.ID
  if @RecordType='bank'
    update AuditCondensed set BankOldValue=OldValue,
      BankNewValue=NewValue
    from AuditCondensed
    join Inserted on Inserted.ID=AuditCondensed.ID
  if @RecordType='branch'
    update AuditCondensed set BranchOldValue=OldValue,
      BranchNewValue=NewValue
    from AuditCondensed
    join Inserted on Inserted.ID=AuditCondensed.ID
go


create trigger trSendEmail on AuditCondensed
after update as
  if exists (select * from Inserted
   where AccountNoNewValue is not null
     and AccountTypeNewValue is not null
     and BankNewValue is not null
     and BranchNewValue is not null)
  begin
    -- sent your email here
  end
go