2010-10-19 8 views
3

Encore une fois .. j'ai le déclencheur ci-dessous qui a la fonction de garder/définir la valeur dans la colonne esb pour 1 rangée maximum à la valeur 0 (dans chaque rangée la valeur cycles de Q-> 0-> R-> 1) Lorsque j'insère plus de 1 ligne, le déclencheur échoue avec une erreur "La sous-requête a renvoyé plus de 1. Cette erreur n'est pas permise lorsque la sous-requête suit" sur la ligne 38, (SELECT esb FROM INSERTED) dans ('1', 'Q')) "statment. Je comprends que 'SELECT esb FROM INSERTED' retournera toutes les lignes de l'insertion, mais ne sait pas comment traiter une ligne à la fois. Je l'ai également essayé en créant une table temporaire et en itérant dans le jeu de résultats, mais j'ai ensuite découvert que les tables temporaires basées sur la table INSERTED ne sont pas autorisées.La sous-requête a renvoyé plus de 1 valeur. Ce n'est pas permis erreur dans AFTER INSERT, UPDATE déclencheur

toutes les suggestions sont les bienvenues (nouveau)

set ANSI_NULLS ON 
set QUOTED_IDENTIFIER ON 
go 

ALTER TRIGGER [TR_PHOTO_AIU] 
    ON   [SOA].[dbo].[photos_TEST] 
    AFTER  INSERT,UPDATE 
AS 

DECLARE @MAXCONC INT -- Maximum concurrent processes 
DECLARE @CONC INT  -- Actual concurrent processes 

SET @MAXCONC = 1  -- 1 concurrent process 

-- SET NOCOUNT ON added to prevent extra result sets from 
-- interfering with SELECT statements. 
SET NOCOUNT ON 

-- If column esb is involved in the update, does not necessarily mean 
-- that the column itself is updated 
If (Update(ESB)) 
BEGIN 
    -- If column esb has been changed to 1 or Q 

    IF ((SELECT esb FROM INSERTED) in ('1','Q')) 
    BEGIN 
     -- count the number of (imminent) active processes 
     SET @CONC = (SELECT COUNT(*) 
        FROM SOA.dbo.photos_TEST pc 
        WHERE pc.esb in ('0','R')) 

     -- if maximum has not been reached 
     IF NOT (@CONC >= @MAXCONC) 
     BEGIN 
      -- set additional rows esb to '0' to match @MAXCONC 
       UPDATE TOP(@[email protected]) p2 
       SET p2.esb = '0' 
      FROM (SELECT TOP(@[email protected]) p1.esb 
        FROM SOA.dbo.photos_TEST p1 
        INNER JOIN INSERTED i ON i.Value = p1.Value 
        AND i.ArrivalDateTime > p1.ArrivalDateTime 
        WHERE p1.esb = 'Q' 
        ORDER BY p1.arrivaldatetime ASC 

      ) p2 

     END 
    END 
END 

Répondre

3

Essayez de Ressaisissez votre IF comme:

IF EXISTS(SELECT 1 FROM INSERTED WHERE esb IN ('1','Q')) 
... 
+0

Merci! Cela a fait l'affaire. Au départ, je pensais que c'était résolu, mais d'autres tests ont montré que cette solution de travail permettait de résoudre le problème. Mais pouvez-vous expliquer pourquoi cela fonctionne? EXISTS comme le IF (SELECTED ... IN ..) font à la fois un booléen ?! – pcvnes

+0

@pcvnes: Comme vous l'avez mentionné dans votre question, lorsque vous insérez plus de 1 ligne, 'SELECT esb FROM INSERTED' renvoie toutes les lignes. Vous pouvez demander si une seule valeur est 'dans 'un ensemble, comme dans' si 5 dans (1,2,5) ... 'mais vous ne pouvez pas demander si un ensemble (comme celui retourné par votre' select') est 'dans 'un autre ensemble comme dans' if (3,5) in (1,2,5) ... 'En utilisant la syntaxe telle que je l'ai écrite, vous posez une question différente:" Are * any * values "dans" cet ensemble? " –