2012-01-18 6 views
0

Je dois construire la logique suivante sur une paire de tables SQL. Voici la structure de la table de base:Déclencheur SQL avec mises à jour conditionnelles

TABLE [dbo].[Email](
    [IssueId] [int] NOT NULL, 
    [NoErrors] [int] NOT NULL, 
    [EmailBody] [nvarchar](max) NULL, 
    ... 
) 

TABLE [dbo].[Inclusion](
    [InclusionId] [int] IDENTITY(1,1) NOT NULL, 
    [IssueId] [int] NOT NULL, 
    ... 
) 

La relation principale pour les deux tables est une table [d'émission] sur le terrain IssueId. Chaque enregistrement de problème n'a qu'une seule table de courrier électronique associée, mais zéro à plusieurs enregistrements d'inclusion.

Ce que je veux arriver est ce ...

Si un enregistrement d'inclusion est supprimé et il a été le dernier enregistrement d'inclusion associée à la question, alors je veux régler les Email.NoErrors à -1. Si d'autres inclusions existent (après la suppression), je souhaite laisser le champ Email.NoErrors 'tel quel'.

J'ai écrit le déclencheur suivant qui semble fonctionner:

ALTER TRIGGER [dbo].[trg_Inclusion_Delete] 
    ON [dbo].[Inclusion] 
    AFTER DELETE 
AS 
BEGIN 
    SET NOCOUNT ON; 

    UPDATE Email 
    SET NoErrors = CASE 
     WHEN EXISTS (
      SELECT * FROM Inclusion 
      WHERE IssueId = DELETED.IssueId 
     ) 
     THEN NoErrors -- Leave existing value 
     ELSE 
     (-1) 
     END 
    FROM DELETED 
    WHERE Email.IssueId = DELETED.IssueId 
END 

Il y a deux choses que je connais assez pour inquiéter. Tout d'abord, le déclencheur semble inefficace car il met toujours à jour le Email.NoErrors classé, même si ce n'est pas obligatoire. Deuxièmement, je suis conscient que la table de référence DELETED peut contenir plus d'un enregistrement mais je ne suis pas sûr que mon script le gère correctement - mais je ne le crois pas.

Tout conseil/direction serait grandement apprécié.

MISE À JOUR
Voici le code final que j'ai fini avec:

ALTER TRIGGER [dbo].[trg_Inclusion_Delete] 
    ON [dbo].[Inclusion] AFTER DELETE 
AS 

IF @@ROWCOUNT = 1 
BEGIN 
    UPDATE Issue 
    SET NoEmailErrors = -1 
    FROM DELETED 
    WHERE (
     Issue.IssueId = DELETED.IssueId 
     AND Issue.NoEmailErrors != -1 
     AND NOT EXISTS (
     SELECT * 
     FROM Inclusion 
     WHERE Inclusion.IssueId = DELETED.IssueId 
    ) 
    ) 
END 
ELSE 
BEGIN 
    UPDATE Issue 
    SET NoEmailErrors = -1 
    FROM DELETED 
    WHERE (
     Issue.IssueId IN (
     SELECT IssueId FROM DELETED 
    ) 
     AND Issue.NoEmailErrors != -1 
     AND NOT EXISTS (
     SELECT * 
     FROM Inclusion 
     WHERE Inclusion.IssueId = DELETED.IssueId 
    ) 
    ) 
END 

Répondre

1

Cette réécriture peut vous aider avec le souci de l'inefficacité:

ALTER TRIGGER [dbo].[trg_Inclusion_Delete] 
    ON [dbo].[Inclusion] 
    AFTER DELETE 
AS 
BEGIN 
SET NOCOUNT ON; 

    UPDATE Email 
    SET NoErrors = -1 
    FROM DELETED 
    WHERE Email.IssueId = DELETED.IssueId 
     AND NOT EXISTS 
     (
      SELECT 'x' FROM Inclusion 
      WHERE Inclusion.IssueId = DELETED.IssueId 
     ) 
END 
+0

Merci Eric, votre code est beaucoup plus propre. J'ai également trouvé le lien suivant http://msdn.microsoft.com/en-us/library/ms190752.aspx qui je pense est pertinent à ce que j'essaye de faire. J'ai mis à jour mon message original pour inclure le nouveau script – Neilski

Questions connexes