J'espère que vous allez pouvoir m'aider car je commence à vraiment tourner
en rond :
Dans mon Trigger, je souhaite comparer 3 valeurs de la table INSERTED à 3
trois valeurs lues dans une autre table pour valider la modification de la
ligne :
Si 1 des 3 valeurs n'est pas identique, je dois annuler la mise à jour
(Rollback).
Voici un peu de code pour être plus clair :
ALTER TRIGGER tr_Verrou_Expedition ON [dbo].[EXPEDITION]
FOR UPDATE
AS
DECLARE @StationMaitre nvarchar(50)
DECLARE @TypeVerrouMaitre tinyint
DECLARE @OperateurMaitre int
DECLARE @Station nvarchar(50)
DECLARE @TypeVerrou tinyint
DECLARE @Operateur int
DECLARE @CptExpedition int
DECLARE @Message nvarchar(4000)
SELECT
@CptExpedition=CptExpedition,@Station=Station,@TypeVerrou=TypeVerrou,@Operateur=Operateur FROM inserted
SELECT
@StationMaitre=Station,@TypeVerrouMaitre=TypeVerrou,@OperateurMaitre=Operateur FROM VERROU WHERE RefCpt=@CptExpedition
Select @Message=' MAJ Exped '+ convert(nvarchar,@CptExpedition) + ' St=' +
convert(nvarchar,@Station) + '=' + convert(nvarchar,@StationMaitre) +'
Op='+convert(nvarchar,@Operateur)+'='+convert(nvarchar,@OperateurMaitre)+'
TypVer=' + convert(nvarchar,@TypeVerrou) + '=' +
convert(nvarchar,@TypeVerrouMaitre)
insert debug (msg) values (@Message)
IF (isnull(len(@StationMaitre),0)=0) AND (isnull(@TypeVerrouMaitre,0)=0) AND
(isnull(@OperateurMaitre,0)=0) --@@ROWCOUNT=1
BEGIN
insert debug (msg) values('RAISERROR('' ROLLBACK Pas de verrou'' , 16, 1)
ROLLBACK TRANSACTION')
END
ELSE
BEGIN
IF (@StationMaitre=@Station) AND (@TypeVerrouMaitre=@TypeVerrou) AND
(@OperateurMaitre=@Operateur)
BEGIN
insert debug (msg) values ('OK')
END
ELSE
BEGIN
insert debug (msg) values ('RAISERROR('' ROLLBACK Mauvais operateur'', 16,
1 )
ROLLBACK TRANSACTION')
END
END
GO
La table debug me permet juste de "voir" le résultat théorique du trigger.
En prod, j'enlèverai l'insert debug pour ne laisser que le contenu de la
valeur ajoutée.
Le problème est que pour modifier 1 seul champ dans la table, j'ai
l'impression que le trigger est activé 3 fois : 2 fois en passant par PAS DE
VERROU et la dernière fois par OK
En production cela ne fonctionnera pas car le Rollback annulera la
transaction avant d'être arrivé à terme.
Je n'arrive pas à comprendre pourquoi il y a des activations qui ne
correspondent pas à ce que je souhaiterai !
Cette action est irreversible, confirmez la suppression du commentaire ?
Signaler le commentaire
Veuillez sélectionner un problème
Nudité
Violence
Harcèlement
Fraude
Vente illégale
Discours haineux
Terrorisme
Autre
Fred BROUARD
Un trigger ne fonctionne pas comme tu le souhaite ! Il fonctionne comme il doit fonctionner...
Un trigger voit passer d'un seul coup TOUTES les modifs de TOUS les tuples en jeu.
Ainsi, lors de l'exécution de l'ordre :
UPDATE EXPEDITION SET Operateur = UPPER(Operateur)
Toutes les lignes de la table seront modifiées. Ce qui veur dire que la pseudo table inserted contiendra autant de lignes qu'il y a de lignes dans la table EXPEDITION.
Donc ton code est déjà anormal puisqu'il présuppose que inserted ne contient jamais qu'une seule ligne !
en effet, a quelle ligne se réfère : SELECT @CptExpedition=CptExpedition, @Station=Station, @TypeVerrou=TypeVerrou, @Operateur=Operateur FROM inserted ???
Pour gérer les effets d'un triggers, il faut, soit gérer le contrôle de manière ensembliste (requête avec intégration de la table inserted liée aux tables en jeu), soit utiliser un curseur (beaucoup moins performant, mais nécessaire lorque le traitement est "au cas par cas").
En l'occurence et à mon avis, ton trigger peut se résumer à :
ALTER TRIGGER tr_Verrou_Expedition ON [dbo].[EXPEDITION] FOR UPDATE AS
IF EXISTS (SELECT * FROM inserted i INNER JOIN VERROU v ON i.CptExpedition = v.RefCpt WHERE i.Station <> v.Station OR i.TypeVerrou <> v.TypeVerrou OR i.Operateur <> v.Operateur) ROLLBACK TRANSACTION GO
C'est tout !
En régle générale, la présence de variable dans un trigger est un bon indice pour montrer que quelque chose ne va pas !
A +
-- Frédéric BROUARD, MVP SQL Server. Expert SQL / spécialiste Delphi, web Livre SQL - col. Référence : http://sqlpro.developpez.com/bookSQL.html Le site du SQL, pour débutants et pros : http://sqlpro.developpez.com ************************ www.datasapiens.com *************************
Arnaud CAVELIER a écrit:
Bonjour,
J'espère que vous allez pouvoir m'aider car je commence à vraiment tourner en rond :
Dans mon Trigger, je souhaite comparer 3 valeurs de la table INSERTED à 3 trois valeurs lues dans une autre table pour valider la modification de la ligne :
Si 1 des 3 valeurs n'est pas identique, je dois annuler la mise à jour (Rollback).
Voici un peu de code pour être plus clair : ALTER TRIGGER tr_Verrou_Expedition ON [dbo].[EXPEDITION] FOR UPDATE AS DECLARE @StationMaitre nvarchar(50) DECLARE @TypeVerrouMaitre tinyint DECLARE @OperateurMaitre int DECLARE @Station nvarchar(50) DECLARE @TypeVerrou tinyint DECLARE @Operateur int DECLARE @CptExpedition int DECLARE @Message nvarchar(4000) SELECT @CptExpedition=CptExpedition,@Station=Station,@TypeVerrou=TypeVerrou,@Operateur=Operateur FROM inserted SELECT @StationMaitre=Station,@TypeVerrouMaitre=TypeVerrou,@OperateurMaitre=Operateur FROM VERROU WHERE RefCpt=@CptExpedition Select @Message=' MAJ Exped '+ convert(nvarchar,@CptExpedition) + ' St=' + convert(nvarchar,@Station) + '=' + convert(nvarchar,@StationMaitre) +' Op='+convert(nvarchar,@Operateur)+'='+convert(nvarchar,@OperateurMaitre)+' TypVer=' + convert(nvarchar,@TypeVerrou) + '=' + convert(nvarchar,@TypeVerrouMaitre) insert debug (msg) values (@Message) IF (isnull(len(@StationMaitre),0)=0) AND (isnull(@TypeVerrouMaitre,0)=0) AND (isnull(@OperateurMaitre,0)=0) --@@ROWCOUNT=1 BEGIN insert debug (msg) values('RAISERROR('' ROLLBACK Pas de verrou'' , 16, 1) ROLLBACK TRANSACTION') END ELSE BEGIN IF (@StationMaitre=@Station) AND (@TypeVerrouMaitre=@TypeVerrou) AND (@OperateurMaitre=@Operateur) BEGIN insert debug (msg) values ('OK') END ELSE BEGIN insert debug (msg) values ('RAISERROR('' ROLLBACK Mauvais operateur'', 16, 1 ) ROLLBACK TRANSACTION') END END
GO
La table debug me permet juste de "voir" le résultat théorique du trigger. En prod, j'enlèverai l'insert debug pour ne laisser que le contenu de la valeur ajoutée.
Le problème est que pour modifier 1 seul champ dans la table, j'ai l'impression que le trigger est activé 3 fois : 2 fois en passant par PAS DE VERROU et la dernière fois par OK En production cela ne fonctionnera pas car le Rollback annulera la transaction avant d'être arrivé à terme.
Je n'arrive pas à comprendre pourquoi il y a des activations qui ne correspondent pas à ce que je souhaiterai !
Merci de votre aide. ac at expedito dot fr
Un trigger ne fonctionne pas comme tu le souhaite ! Il fonctionne comme il doit
fonctionner...
Un trigger voit passer d'un seul coup TOUTES les modifs de TOUS les tuples en jeu.
Ainsi, lors de l'exécution de l'ordre :
UPDATE EXPEDITION
SET Operateur = UPPER(Operateur)
Toutes les lignes de la table seront modifiées.
Ce qui veur dire que la pseudo table inserted contiendra autant de lignes qu'il
y a de lignes dans la table EXPEDITION.
Donc ton code est déjà anormal puisqu'il présuppose que inserted ne contient
jamais qu'une seule ligne !
en effet, a quelle ligne se réfère :
SELECT @CptExpedition=CptExpedition,
@Station=Station,
@TypeVerrou=TypeVerrou,
@Operateur=Operateur
FROM inserted
???
Pour gérer les effets d'un triggers, il faut, soit gérer le contrôle de manière
ensembliste (requête avec intégration de la table inserted liée aux tables en
jeu), soit utiliser un curseur (beaucoup moins performant, mais nécessaire
lorque le traitement est "au cas par cas").
En l'occurence et à mon avis, ton trigger peut se résumer à :
ALTER TRIGGER tr_Verrou_Expedition ON [dbo].[EXPEDITION]
FOR UPDATE
AS
IF EXISTS (SELECT *
FROM inserted i
INNER JOIN VERROU v
ON i.CptExpedition = v.RefCpt
WHERE i.Station <> v.Station
OR i.TypeVerrou <> v.TypeVerrou
OR i.Operateur <> v.Operateur)
ROLLBACK TRANSACTION
GO
C'est tout !
En régle générale, la présence de variable dans un trigger est un bon indice
pour montrer que quelque chose ne va pas !
A +
--
Frédéric BROUARD, MVP SQL Server. Expert SQL / spécialiste Delphi, web
Livre SQL - col. Référence : http://sqlpro.developpez.com/bookSQL.html
Le site du SQL, pour débutants et pros : http://sqlpro.developpez.com
************************ www.datasapiens.com *************************
Arnaud CAVELIER a écrit:
Bonjour,
J'espère que vous allez pouvoir m'aider car je commence à vraiment tourner
en rond :
Dans mon Trigger, je souhaite comparer 3 valeurs de la table INSERTED à 3
trois valeurs lues dans une autre table pour valider la modification de la
ligne :
Si 1 des 3 valeurs n'est pas identique, je dois annuler la mise à jour
(Rollback).
Voici un peu de code pour être plus clair :
ALTER TRIGGER tr_Verrou_Expedition ON [dbo].[EXPEDITION]
FOR UPDATE
AS
DECLARE @StationMaitre nvarchar(50)
DECLARE @TypeVerrouMaitre tinyint
DECLARE @OperateurMaitre int
DECLARE @Station nvarchar(50)
DECLARE @TypeVerrou tinyint
DECLARE @Operateur int
DECLARE @CptExpedition int
DECLARE @Message nvarchar(4000)
SELECT
@CptExpedition=CptExpedition,@Station=Station,@TypeVerrou=TypeVerrou,@Operateur=Operateur FROM inserted
SELECT
@StationMaitre=Station,@TypeVerrouMaitre=TypeVerrou,@OperateurMaitre=Operateur FROM VERROU WHERE RefCpt=@CptExpedition
Select @Message=' MAJ Exped '+ convert(nvarchar,@CptExpedition) + ' St=' +
convert(nvarchar,@Station) + '=' + convert(nvarchar,@StationMaitre) +'
Op='+convert(nvarchar,@Operateur)+'='+convert(nvarchar,@OperateurMaitre)+'
TypVer=' + convert(nvarchar,@TypeVerrou) + '=' +
convert(nvarchar,@TypeVerrouMaitre)
insert debug (msg) values (@Message)
IF (isnull(len(@StationMaitre),0)=0) AND (isnull(@TypeVerrouMaitre,0)=0) AND
(isnull(@OperateurMaitre,0)=0) --@@ROWCOUNT=1
BEGIN
insert debug (msg) values('RAISERROR('' ROLLBACK Pas de verrou'' , 16, 1)
ROLLBACK TRANSACTION')
END
ELSE
BEGIN
IF (@StationMaitre=@Station) AND (@TypeVerrouMaitre=@TypeVerrou) AND
(@OperateurMaitre=@Operateur)
BEGIN
insert debug (msg) values ('OK')
END
ELSE
BEGIN
insert debug (msg) values ('RAISERROR('' ROLLBACK Mauvais operateur'', 16,
1 )
ROLLBACK TRANSACTION')
END
END
GO
La table debug me permet juste de "voir" le résultat théorique du trigger.
En prod, j'enlèverai l'insert debug pour ne laisser que le contenu de la
valeur ajoutée.
Le problème est que pour modifier 1 seul champ dans la table, j'ai
l'impression que le trigger est activé 3 fois : 2 fois en passant par PAS DE
VERROU et la dernière fois par OK
En production cela ne fonctionnera pas car le Rollback annulera la
transaction avant d'être arrivé à terme.
Je n'arrive pas à comprendre pourquoi il y a des activations qui ne
correspondent pas à ce que je souhaiterai !
Un trigger ne fonctionne pas comme tu le souhaite ! Il fonctionne comme il doit fonctionner...
Un trigger voit passer d'un seul coup TOUTES les modifs de TOUS les tuples en jeu.
Ainsi, lors de l'exécution de l'ordre :
UPDATE EXPEDITION SET Operateur = UPPER(Operateur)
Toutes les lignes de la table seront modifiées. Ce qui veur dire que la pseudo table inserted contiendra autant de lignes qu'il y a de lignes dans la table EXPEDITION.
Donc ton code est déjà anormal puisqu'il présuppose que inserted ne contient jamais qu'une seule ligne !
en effet, a quelle ligne se réfère : SELECT @CptExpedition=CptExpedition, @Station=Station, @TypeVerrou=TypeVerrou, @Operateur=Operateur FROM inserted ???
Pour gérer les effets d'un triggers, il faut, soit gérer le contrôle de manière ensembliste (requête avec intégration de la table inserted liée aux tables en jeu), soit utiliser un curseur (beaucoup moins performant, mais nécessaire lorque le traitement est "au cas par cas").
En l'occurence et à mon avis, ton trigger peut se résumer à :
ALTER TRIGGER tr_Verrou_Expedition ON [dbo].[EXPEDITION] FOR UPDATE AS
IF EXISTS (SELECT * FROM inserted i INNER JOIN VERROU v ON i.CptExpedition = v.RefCpt WHERE i.Station <> v.Station OR i.TypeVerrou <> v.TypeVerrou OR i.Operateur <> v.Operateur) ROLLBACK TRANSACTION GO
C'est tout !
En régle générale, la présence de variable dans un trigger est un bon indice pour montrer que quelque chose ne va pas !
A +
-- Frédéric BROUARD, MVP SQL Server. Expert SQL / spécialiste Delphi, web Livre SQL - col. Référence : http://sqlpro.developpez.com/bookSQL.html Le site du SQL, pour débutants et pros : http://sqlpro.developpez.com ************************ www.datasapiens.com *************************
Arnaud CAVELIER a écrit:
Bonjour,
J'espère que vous allez pouvoir m'aider car je commence à vraiment tourner en rond :
Dans mon Trigger, je souhaite comparer 3 valeurs de la table INSERTED à 3 trois valeurs lues dans une autre table pour valider la modification de la ligne :
Si 1 des 3 valeurs n'est pas identique, je dois annuler la mise à jour (Rollback).
Voici un peu de code pour être plus clair : ALTER TRIGGER tr_Verrou_Expedition ON [dbo].[EXPEDITION] FOR UPDATE AS DECLARE @StationMaitre nvarchar(50) DECLARE @TypeVerrouMaitre tinyint DECLARE @OperateurMaitre int DECLARE @Station nvarchar(50) DECLARE @TypeVerrou tinyint DECLARE @Operateur int DECLARE @CptExpedition int DECLARE @Message nvarchar(4000) SELECT @CptExpedition=CptExpedition,@Station=Station,@TypeVerrou=TypeVerrou,@Operateur=Operateur FROM inserted SELECT @StationMaitre=Station,@TypeVerrouMaitre=TypeVerrou,@OperateurMaitre=Operateur FROM VERROU WHERE RefCpt=@CptExpedition Select @Message=' MAJ Exped '+ convert(nvarchar,@CptExpedition) + ' St=' + convert(nvarchar,@Station) + '=' + convert(nvarchar,@StationMaitre) +' Op='+convert(nvarchar,@Operateur)+'='+convert(nvarchar,@OperateurMaitre)+' TypVer=' + convert(nvarchar,@TypeVerrou) + '=' + convert(nvarchar,@TypeVerrouMaitre) insert debug (msg) values (@Message) IF (isnull(len(@StationMaitre),0)=0) AND (isnull(@TypeVerrouMaitre,0)=0) AND (isnull(@OperateurMaitre,0)=0) --@@ROWCOUNT=1 BEGIN insert debug (msg) values('RAISERROR('' ROLLBACK Pas de verrou'' , 16, 1) ROLLBACK TRANSACTION') END ELSE BEGIN IF (@StationMaitre=@Station) AND (@TypeVerrouMaitre=@TypeVerrou) AND (@OperateurMaitre=@Operateur) BEGIN insert debug (msg) values ('OK') END ELSE BEGIN insert debug (msg) values ('RAISERROR('' ROLLBACK Mauvais operateur'', 16, 1 ) ROLLBACK TRANSACTION') END END
GO
La table debug me permet juste de "voir" le résultat théorique du trigger. En prod, j'enlèverai l'insert debug pour ne laisser que le contenu de la valeur ajoutée.
Le problème est que pour modifier 1 seul champ dans la table, j'ai l'impression que le trigger est activé 3 fois : 2 fois en passant par PAS DE VERROU et la dernière fois par OK En production cela ne fonctionnera pas car le Rollback annulera la transaction avant d'être arrivé à terme.
Je n'arrive pas à comprendre pourquoi il y a des activations qui ne correspondent pas à ce que je souhaiterai !
Merci de votre aide. ac at expedito dot fr
Sylvain Lafontaine
À mon avis, vouloir utiliser les triggers pour valider une insertion/modification APRÈS-COUP n'est probablement pas une bonne idée.
Vous seriez mieux de faire cette vérification avant même d'essayer de faire la mise-à-jour, dans une procédure stockée ou même dans votre code VBA; sinon vous allez finir par avoir du code complètement immangeable. Comme les trois champs doivent être identiques entre deux tables différentes, on peut également se poser des questions sur la Normalité de votre bdd.
Les triggers ne devraient être utilisées que pour des choses simples, comme la mise-à-jour d'un champ stockant la dernière date de modification et autre gugus du genre; sinon votre bdd va devenir un vrai labyrinthe.
S. L.
"Arnaud CAVELIER" wrote in message news:
Bonjour,
J'espère que vous allez pouvoir m'aider car je commence à vraiment tourner en rond :
Dans mon Trigger, je souhaite comparer 3 valeurs de la table INSERTED à 3 trois valeurs lues dans une autre table pour valider la modification de la ligne :
Si 1 des 3 valeurs n'est pas identique, je dois annuler la mise à jour (Rollback).
Voici un peu de code pour être plus clair : ALTER TRIGGER tr_Verrou_Expedition ON [dbo].[EXPEDITION] FOR UPDATE AS DECLARE @StationMaitre nvarchar(50) DECLARE @TypeVerrouMaitre tinyint DECLARE @OperateurMaitre int DECLARE @Station nvarchar(50) DECLARE @TypeVerrou tinyint DECLARE @Operateur int DECLARE @CptExpedition int DECLARE @Message nvarchar(4000) SELECT @CptExpedition=CptExpedition,@Station=Station,@TypeVerrou=TypeVerrou,@Operateur=Operateur FROM inserted SELECT @StationMaitre=Station,@TypeVerrouMaitre=TypeVerrou,@OperateurMaitre=Operateur FROM VERROU WHERE RefCpt=@CptExpedition Select @Message=' MAJ Exped '+ convert(nvarchar,@CptExpedition) + ' St=' + convert(nvarchar,@Station) + '=' + convert(nvarchar,@StationMaitre) +' Op='+convert(nvarchar,@Operateur)+'='+convert(nvarchar,@OperateurMaitre)+' TypVer=' + convert(nvarchar,@TypeVerrou) + '=' + convert(nvarchar,@TypeVerrouMaitre) insert debug (msg) values (@Message) IF (isnull(len(@StationMaitre),0)=0) AND (isnull(@TypeVerrouMaitre,0)=0) AND (isnull(@OperateurMaitre,0)=0) --@@ROWCOUNT=1 BEGIN insert debug (msg) values('RAISERROR('' ROLLBACK Pas de verrou'' , 16, 1) ROLLBACK TRANSACTION') END ELSE BEGIN IF (@StationMaitre=@Station) AND (@TypeVerrouMaitre=@TypeVerrou) AND (@OperateurMaitre=@Operateur) BEGIN insert debug (msg) values ('OK') END ELSE BEGIN insert debug (msg) values ('RAISERROR('' ROLLBACK Mauvais operateur'', 16, 1 ) ROLLBACK TRANSACTION') END END
GO
La table debug me permet juste de "voir" le résultat théorique du trigger. En prod, j'enlèverai l'insert debug pour ne laisser que le contenu de la valeur ajoutée.
Le problème est que pour modifier 1 seul champ dans la table, j'ai l'impression que le trigger est activé 3 fois : 2 fois en passant par PAS DE VERROU et la dernière fois par OK En production cela ne fonctionnera pas car le Rollback annulera la transaction avant d'être arrivé à terme.
Je n'arrive pas à comprendre pourquoi il y a des activations qui ne correspondent pas à ce que je souhaiterai !
Merci de votre aide. ac at expedito dot fr
À mon avis, vouloir utiliser les triggers pour valider une
insertion/modification APRÈS-COUP n'est probablement pas une bonne idée.
Vous seriez mieux de faire cette vérification avant même d'essayer de faire
la mise-à-jour, dans une procédure stockée ou même dans votre code VBA;
sinon vous allez finir par avoir du code complètement immangeable. Comme
les trois champs doivent être identiques entre deux tables différentes, on
peut également se poser des questions sur la Normalité de votre bdd.
Les triggers ne devraient être utilisées que pour des choses simples, comme
la mise-à-jour d'un champ stockant la dernière date de modification et autre
gugus du genre; sinon votre bdd va devenir un vrai labyrinthe.
S. L.
"Arnaud CAVELIER" <ArnaudCAVELIER@discussions.microsoft.com> wrote in
message news:8C1720EB-1DEC-4D9E-950F-9EDAE3242AB0@microsoft.com...
Bonjour,
J'espère que vous allez pouvoir m'aider car je commence à vraiment tourner
en rond :
Dans mon Trigger, je souhaite comparer 3 valeurs de la table INSERTED à 3
trois valeurs lues dans une autre table pour valider la modification de la
ligne :
Si 1 des 3 valeurs n'est pas identique, je dois annuler la mise à jour
(Rollback).
Voici un peu de code pour être plus clair :
ALTER TRIGGER tr_Verrou_Expedition ON [dbo].[EXPEDITION]
FOR UPDATE
AS
DECLARE @StationMaitre nvarchar(50)
DECLARE @TypeVerrouMaitre tinyint
DECLARE @OperateurMaitre int
DECLARE @Station nvarchar(50)
DECLARE @TypeVerrou tinyint
DECLARE @Operateur int
DECLARE @CptExpedition int
DECLARE @Message nvarchar(4000)
SELECT
@CptExpedition=CptExpedition,@Station=Station,@TypeVerrou=TypeVerrou,@Operateur=Operateur
FROM inserted
SELECT
@StationMaitre=Station,@TypeVerrouMaitre=TypeVerrou,@OperateurMaitre=Operateur
FROM VERROU WHERE RefCpt=@CptExpedition
Select @Message=' MAJ Exped '+ convert(nvarchar,@CptExpedition) + ' St=' +
convert(nvarchar,@Station) + '=' + convert(nvarchar,@StationMaitre) +'
Op='+convert(nvarchar,@Operateur)+'='+convert(nvarchar,@OperateurMaitre)+'
TypVer=' + convert(nvarchar,@TypeVerrou) + '=' +
convert(nvarchar,@TypeVerrouMaitre)
insert debug (msg) values (@Message)
IF (isnull(len(@StationMaitre),0)=0) AND (isnull(@TypeVerrouMaitre,0)=0)
AND
(isnull(@OperateurMaitre,0)=0) --@@ROWCOUNT=1
BEGIN
insert debug (msg) values('RAISERROR('' ROLLBACK Pas de verrou'' , 16, 1)
ROLLBACK TRANSACTION')
END
ELSE
BEGIN
IF (@StationMaitre=@Station) AND (@TypeVerrouMaitre=@TypeVerrou) AND
(@OperateurMaitre=@Operateur)
BEGIN
insert debug (msg) values ('OK')
END
ELSE
BEGIN
insert debug (msg) values ('RAISERROR('' ROLLBACK Mauvais operateur'', 16,
1 )
ROLLBACK TRANSACTION')
END
END
GO
La table debug me permet juste de "voir" le résultat théorique du trigger.
En prod, j'enlèverai l'insert debug pour ne laisser que le contenu de la
valeur ajoutée.
Le problème est que pour modifier 1 seul champ dans la table, j'ai
l'impression que le trigger est activé 3 fois : 2 fois en passant par PAS
DE
VERROU et la dernière fois par OK
En production cela ne fonctionnera pas car le Rollback annulera la
transaction avant d'être arrivé à terme.
Je n'arrive pas à comprendre pourquoi il y a des activations qui ne
correspondent pas à ce que je souhaiterai !
À mon avis, vouloir utiliser les triggers pour valider une insertion/modification APRÈS-COUP n'est probablement pas une bonne idée.
Vous seriez mieux de faire cette vérification avant même d'essayer de faire la mise-à-jour, dans une procédure stockée ou même dans votre code VBA; sinon vous allez finir par avoir du code complètement immangeable. Comme les trois champs doivent être identiques entre deux tables différentes, on peut également se poser des questions sur la Normalité de votre bdd.
Les triggers ne devraient être utilisées que pour des choses simples, comme la mise-à-jour d'un champ stockant la dernière date de modification et autre gugus du genre; sinon votre bdd va devenir un vrai labyrinthe.
S. L.
"Arnaud CAVELIER" wrote in message news:
Bonjour,
J'espère que vous allez pouvoir m'aider car je commence à vraiment tourner en rond :
Dans mon Trigger, je souhaite comparer 3 valeurs de la table INSERTED à 3 trois valeurs lues dans une autre table pour valider la modification de la ligne :
Si 1 des 3 valeurs n'est pas identique, je dois annuler la mise à jour (Rollback).
Voici un peu de code pour être plus clair : ALTER TRIGGER tr_Verrou_Expedition ON [dbo].[EXPEDITION] FOR UPDATE AS DECLARE @StationMaitre nvarchar(50) DECLARE @TypeVerrouMaitre tinyint DECLARE @OperateurMaitre int DECLARE @Station nvarchar(50) DECLARE @TypeVerrou tinyint DECLARE @Operateur int DECLARE @CptExpedition int DECLARE @Message nvarchar(4000) SELECT @CptExpedition=CptExpedition,@Station=Station,@TypeVerrou=TypeVerrou,@Operateur=Operateur FROM inserted SELECT @StationMaitre=Station,@TypeVerrouMaitre=TypeVerrou,@OperateurMaitre=Operateur FROM VERROU WHERE RefCpt=@CptExpedition Select @Message=' MAJ Exped '+ convert(nvarchar,@CptExpedition) + ' St=' + convert(nvarchar,@Station) + '=' + convert(nvarchar,@StationMaitre) +' Op='+convert(nvarchar,@Operateur)+'='+convert(nvarchar,@OperateurMaitre)+' TypVer=' + convert(nvarchar,@TypeVerrou) + '=' + convert(nvarchar,@TypeVerrouMaitre) insert debug (msg) values (@Message) IF (isnull(len(@StationMaitre),0)=0) AND (isnull(@TypeVerrouMaitre,0)=0) AND (isnull(@OperateurMaitre,0)=0) --@@ROWCOUNT=1 BEGIN insert debug (msg) values('RAISERROR('' ROLLBACK Pas de verrou'' , 16, 1) ROLLBACK TRANSACTION') END ELSE BEGIN IF (@StationMaitre=@Station) AND (@TypeVerrouMaitre=@TypeVerrou) AND (@OperateurMaitre=@Operateur) BEGIN insert debug (msg) values ('OK') END ELSE BEGIN insert debug (msg) values ('RAISERROR('' ROLLBACK Mauvais operateur'', 16, 1 ) ROLLBACK TRANSACTION') END END
GO
La table debug me permet juste de "voir" le résultat théorique du trigger. En prod, j'enlèverai l'insert debug pour ne laisser que le contenu de la valeur ajoutée.
Le problème est que pour modifier 1 seul champ dans la table, j'ai l'impression que le trigger est activé 3 fois : 2 fois en passant par PAS DE VERROU et la dernière fois par OK En production cela ne fonctionnera pas car le Rollback annulera la transaction avant d'être arrivé à terme.
Je n'arrive pas à comprendre pourquoi il y a des activations qui ne correspondent pas à ce que je souhaiterai !
Merci de votre aide. ac at expedito dot fr
Arnaud CAVELIER
Ce sont effectivement mes débuts avec des triggers.
MERCI des infos
A bientôt, Arnaud
"Fred BROUARD" a écrit :
Un trigger ne fonctionne pas comme tu le souhaite ! Il fonctionne comme il doit fonctionner...
Un trigger voit passer d'un seul coup TOUTES les modifs de TOUS les tuples en jeu.
Ainsi, lors de l'exécution de l'ordre :
UPDATE EXPEDITION SET Operateur = UPPER(Operateur)
Toutes les lignes de la table seront modifiées. Ce qui veur dire que la pseudo table inserted contiendra autant de lignes qu'il y a de lignes dans la table EXPEDITION.
Donc ton code est déjà anormal puisqu'il présuppose que inserted ne contient jamais qu'une seule ligne !
en effet, a quelle ligne se réfère : SELECT @CptExpedition=CptExpedition, @Station=Station, @TypeVerrou=TypeVerrou, @Operateur=Operateur FROM inserted ???
Pour gérer les effets d'un triggers, il faut, soit gérer le contrôle de manière ensembliste (requête avec intégration de la table inserted liée aux tables en jeu), soit utiliser un curseur (beaucoup moins performant, mais nécessaire lorque le traitement est "au cas par cas").
En l'occurence et à mon avis, ton trigger peut se résumer à :
ALTER TRIGGER tr_Verrou_Expedition ON [dbo].[EXPEDITION] FOR UPDATE AS
IF EXISTS (SELECT * FROM inserted i INNER JOIN VERROU v ON i.CptExpedition = v.RefCpt WHERE i.Station <> v.Station OR i.TypeVerrou <> v.TypeVerrou OR i.Operateur <> v.Operateur) ROLLBACK TRANSACTION GO
C'est tout !
En régle générale, la présence de variable dans un trigger est un bon indice pour montrer que quelque chose ne va pas !
A +
-- Frédéric BROUARD, MVP SQL Server. Expert SQL / spécialiste Delphi, web Livre SQL - col. Référence : http://sqlpro.developpez.com/bookSQL.html Le site du SQL, pour débutants et pros : http://sqlpro.developpez.com ************************ www.datasapiens.com *************************
Arnaud CAVELIER a écrit: > Bonjour, > > J'espère que vous allez pouvoir m'aider car je commence à vraiment tourner > en rond : > > Dans mon Trigger, je souhaite comparer 3 valeurs de la table INSERTED à 3 > trois valeurs lues dans une autre table pour valider la modification de la > ligne : > > Si 1 des 3 valeurs n'est pas identique, je dois annuler la mise à jour > (Rollback). > > Voici un peu de code pour être plus clair : > ALTER TRIGGER tr_Verrou_Expedition ON [dbo].[EXPEDITION] > FOR UPDATE > AS > DECLARE @StationMaitre nvarchar(50) > DECLARE @TypeVerrouMaitre tinyint > DECLARE @OperateurMaitre int > DECLARE @Station nvarchar(50) > DECLARE @TypeVerrou tinyint > DECLARE @Operateur int > DECLARE @CptExpedition int > DECLARE @Message nvarchar(4000) > SELECT > @CptExpedition=CptExpedition,@Station=Station,@TypeVerrou=TypeVerrou,@Operateur=Operateur FROM inserted > SELECT > @StationMaitre=Station,@TypeVerrouMaitre=TypeVerrou,@OperateurMaitre=Operateur FROM VERROU WHERE RefCpt=@CptExpedition > Select @Message=' MAJ Exped '+ convert(nvarchar,@CptExpedition) + ' St=' + > convert(nvarchar,@Station) + '=' + convert(nvarchar,@StationMaitre) +' > Op='+convert(nvarchar,@Operateur)+'='+convert(nvarchar,@OperateurMaitre)+' > TypVer=' + convert(nvarchar,@TypeVerrou) + '=' + > convert(nvarchar,@TypeVerrouMaitre) > insert debug (msg) values (@Message) > IF (isnull(len(@StationMaitre),0)=0) AND (isnull(@TypeVerrouMaitre,0)=0) AND > (isnull(@OperateurMaitre,0)=0) --@@ROWCOUNT=1 > BEGIN > insert debug (msg) values('RAISERROR('' ROLLBACK Pas de verrou'' , 16, 1) > ROLLBACK TRANSACTION') > END > ELSE > BEGIN > IF (@StationMaitre=@Station) AND (@TypeVerrouMaitre=@TypeVerrou) AND > (@OperateurMaitre=@Operateur) > BEGIN > insert debug (msg) values ('OK') > END > ELSE > BEGIN > insert debug (msg) values ('RAISERROR('' ROLLBACK Mauvais operateur'', 16, > 1 ) > ROLLBACK TRANSACTION') > END > END > > GO > > La table debug me permet juste de "voir" le résultat théorique du trigger. > En prod, j'enlèverai l'insert debug pour ne laisser que le contenu de la > valeur ajoutée. > > Le problème est que pour modifier 1 seul champ dans la table, j'ai > l'impression que le trigger est activé 3 fois : 2 fois en passant par PAS DE > VERROU et la dernière fois par OK > En production cela ne fonctionnera pas car le Rollback annulera la > transaction avant d'être arrivé à terme. > > Je n'arrive pas à comprendre pourquoi il y a des activations qui ne > correspondent pas à ce que je souhaiterai ! > > > Merci de votre aide. > ac at expedito dot fr
Ce sont effectivement mes débuts avec des triggers.
MERCI des infos
A bientôt,
Arnaud
"Fred BROUARD" a écrit :
Un trigger ne fonctionne pas comme tu le souhaite ! Il fonctionne comme il doit
fonctionner...
Un trigger voit passer d'un seul coup TOUTES les modifs de TOUS les tuples en jeu.
Ainsi, lors de l'exécution de l'ordre :
UPDATE EXPEDITION
SET Operateur = UPPER(Operateur)
Toutes les lignes de la table seront modifiées.
Ce qui veur dire que la pseudo table inserted contiendra autant de lignes qu'il
y a de lignes dans la table EXPEDITION.
Donc ton code est déjà anormal puisqu'il présuppose que inserted ne contient
jamais qu'une seule ligne !
en effet, a quelle ligne se réfère :
SELECT @CptExpedition=CptExpedition,
@Station=Station,
@TypeVerrou=TypeVerrou,
@Operateur=Operateur
FROM inserted
???
Pour gérer les effets d'un triggers, il faut, soit gérer le contrôle de manière
ensembliste (requête avec intégration de la table inserted liée aux tables en
jeu), soit utiliser un curseur (beaucoup moins performant, mais nécessaire
lorque le traitement est "au cas par cas").
En l'occurence et à mon avis, ton trigger peut se résumer à :
ALTER TRIGGER tr_Verrou_Expedition ON [dbo].[EXPEDITION]
FOR UPDATE
AS
IF EXISTS (SELECT *
FROM inserted i
INNER JOIN VERROU v
ON i.CptExpedition = v.RefCpt
WHERE i.Station <> v.Station
OR i.TypeVerrou <> v.TypeVerrou
OR i.Operateur <> v.Operateur)
ROLLBACK TRANSACTION
GO
C'est tout !
En régle générale, la présence de variable dans un trigger est un bon indice
pour montrer que quelque chose ne va pas !
A +
--
Frédéric BROUARD, MVP SQL Server. Expert SQL / spécialiste Delphi, web
Livre SQL - col. Référence : http://sqlpro.developpez.com/bookSQL.html
Le site du SQL, pour débutants et pros : http://sqlpro.developpez.com
************************ www.datasapiens.com *************************
Arnaud CAVELIER a écrit:
> Bonjour,
>
> J'espère que vous allez pouvoir m'aider car je commence à vraiment tourner
> en rond :
>
> Dans mon Trigger, je souhaite comparer 3 valeurs de la table INSERTED à 3
> trois valeurs lues dans une autre table pour valider la modification de la
> ligne :
>
> Si 1 des 3 valeurs n'est pas identique, je dois annuler la mise à jour
> (Rollback).
>
> Voici un peu de code pour être plus clair :
> ALTER TRIGGER tr_Verrou_Expedition ON [dbo].[EXPEDITION]
> FOR UPDATE
> AS
> DECLARE @StationMaitre nvarchar(50)
> DECLARE @TypeVerrouMaitre tinyint
> DECLARE @OperateurMaitre int
> DECLARE @Station nvarchar(50)
> DECLARE @TypeVerrou tinyint
> DECLARE @Operateur int
> DECLARE @CptExpedition int
> DECLARE @Message nvarchar(4000)
> SELECT
> @CptExpedition=CptExpedition,@Station=Station,@TypeVerrou=TypeVerrou,@Operateur=Operateur FROM inserted
> SELECT
> @StationMaitre=Station,@TypeVerrouMaitre=TypeVerrou,@OperateurMaitre=Operateur FROM VERROU WHERE RefCpt=@CptExpedition
> Select @Message=' MAJ Exped '+ convert(nvarchar,@CptExpedition) + ' St=' +
> convert(nvarchar,@Station) + '=' + convert(nvarchar,@StationMaitre) +'
> Op='+convert(nvarchar,@Operateur)+'='+convert(nvarchar,@OperateurMaitre)+'
> TypVer=' + convert(nvarchar,@TypeVerrou) + '=' +
> convert(nvarchar,@TypeVerrouMaitre)
> insert debug (msg) values (@Message)
> IF (isnull(len(@StationMaitre),0)=0) AND (isnull(@TypeVerrouMaitre,0)=0) AND
> (isnull(@OperateurMaitre,0)=0) --@@ROWCOUNT=1
> BEGIN
> insert debug (msg) values('RAISERROR('' ROLLBACK Pas de verrou'' , 16, 1)
> ROLLBACK TRANSACTION')
> END
> ELSE
> BEGIN
> IF (@StationMaitre=@Station) AND (@TypeVerrouMaitre=@TypeVerrou) AND
> (@OperateurMaitre=@Operateur)
> BEGIN
> insert debug (msg) values ('OK')
> END
> ELSE
> BEGIN
> insert debug (msg) values ('RAISERROR('' ROLLBACK Mauvais operateur'', 16,
> 1 )
> ROLLBACK TRANSACTION')
> END
> END
>
> GO
>
> La table debug me permet juste de "voir" le résultat théorique du trigger.
> En prod, j'enlèverai l'insert debug pour ne laisser que le contenu de la
> valeur ajoutée.
>
> Le problème est que pour modifier 1 seul champ dans la table, j'ai
> l'impression que le trigger est activé 3 fois : 2 fois en passant par PAS DE
> VERROU et la dernière fois par OK
> En production cela ne fonctionnera pas car le Rollback annulera la
> transaction avant d'être arrivé à terme.
>
> Je n'arrive pas à comprendre pourquoi il y a des activations qui ne
> correspondent pas à ce que je souhaiterai !
>
>
> Merci de votre aide.
> ac at expedito dot fr
Ce sont effectivement mes débuts avec des triggers.
MERCI des infos
A bientôt, Arnaud
"Fred BROUARD" a écrit :
Un trigger ne fonctionne pas comme tu le souhaite ! Il fonctionne comme il doit fonctionner...
Un trigger voit passer d'un seul coup TOUTES les modifs de TOUS les tuples en jeu.
Ainsi, lors de l'exécution de l'ordre :
UPDATE EXPEDITION SET Operateur = UPPER(Operateur)
Toutes les lignes de la table seront modifiées. Ce qui veur dire que la pseudo table inserted contiendra autant de lignes qu'il y a de lignes dans la table EXPEDITION.
Donc ton code est déjà anormal puisqu'il présuppose que inserted ne contient jamais qu'une seule ligne !
en effet, a quelle ligne se réfère : SELECT @CptExpedition=CptExpedition, @Station=Station, @TypeVerrou=TypeVerrou, @Operateur=Operateur FROM inserted ???
Pour gérer les effets d'un triggers, il faut, soit gérer le contrôle de manière ensembliste (requête avec intégration de la table inserted liée aux tables en jeu), soit utiliser un curseur (beaucoup moins performant, mais nécessaire lorque le traitement est "au cas par cas").
En l'occurence et à mon avis, ton trigger peut se résumer à :
ALTER TRIGGER tr_Verrou_Expedition ON [dbo].[EXPEDITION] FOR UPDATE AS
IF EXISTS (SELECT * FROM inserted i INNER JOIN VERROU v ON i.CptExpedition = v.RefCpt WHERE i.Station <> v.Station OR i.TypeVerrou <> v.TypeVerrou OR i.Operateur <> v.Operateur) ROLLBACK TRANSACTION GO
C'est tout !
En régle générale, la présence de variable dans un trigger est un bon indice pour montrer que quelque chose ne va pas !
A +
-- Frédéric BROUARD, MVP SQL Server. Expert SQL / spécialiste Delphi, web Livre SQL - col. Référence : http://sqlpro.developpez.com/bookSQL.html Le site du SQL, pour débutants et pros : http://sqlpro.developpez.com ************************ www.datasapiens.com *************************
Arnaud CAVELIER a écrit: > Bonjour, > > J'espère que vous allez pouvoir m'aider car je commence à vraiment tourner > en rond : > > Dans mon Trigger, je souhaite comparer 3 valeurs de la table INSERTED à 3 > trois valeurs lues dans une autre table pour valider la modification de la > ligne : > > Si 1 des 3 valeurs n'est pas identique, je dois annuler la mise à jour > (Rollback). > > Voici un peu de code pour être plus clair : > ALTER TRIGGER tr_Verrou_Expedition ON [dbo].[EXPEDITION] > FOR UPDATE > AS > DECLARE @StationMaitre nvarchar(50) > DECLARE @TypeVerrouMaitre tinyint > DECLARE @OperateurMaitre int > DECLARE @Station nvarchar(50) > DECLARE @TypeVerrou tinyint > DECLARE @Operateur int > DECLARE @CptExpedition int > DECLARE @Message nvarchar(4000) > SELECT > @CptExpedition=CptExpedition,@Station=Station,@TypeVerrou=TypeVerrou,@Operateur=Operateur FROM inserted > SELECT > @StationMaitre=Station,@TypeVerrouMaitre=TypeVerrou,@OperateurMaitre=Operateur FROM VERROU WHERE RefCpt=@CptExpedition > Select @Message=' MAJ Exped '+ convert(nvarchar,@CptExpedition) + ' St=' + > convert(nvarchar,@Station) + '=' + convert(nvarchar,@StationMaitre) +' > Op='+convert(nvarchar,@Operateur)+'='+convert(nvarchar,@OperateurMaitre)+' > TypVer=' + convert(nvarchar,@TypeVerrou) + '=' + > convert(nvarchar,@TypeVerrouMaitre) > insert debug (msg) values (@Message) > IF (isnull(len(@StationMaitre),0)=0) AND (isnull(@TypeVerrouMaitre,0)=0) AND > (isnull(@OperateurMaitre,0)=0) --@@ROWCOUNT=1 > BEGIN > insert debug (msg) values('RAISERROR('' ROLLBACK Pas de verrou'' , 16, 1) > ROLLBACK TRANSACTION') > END > ELSE > BEGIN > IF (@StationMaitre=@Station) AND (@TypeVerrouMaitre=@TypeVerrou) AND > (@OperateurMaitre=@Operateur) > BEGIN > insert debug (msg) values ('OK') > END > ELSE > BEGIN > insert debug (msg) values ('RAISERROR('' ROLLBACK Mauvais operateur'', 16, > 1 ) > ROLLBACK TRANSACTION') > END > END > > GO > > La table debug me permet juste de "voir" le résultat théorique du trigger. > En prod, j'enlèverai l'insert debug pour ne laisser que le contenu de la > valeur ajoutée. > > Le problème est que pour modifier 1 seul champ dans la table, j'ai > l'impression que le trigger est activé 3 fois : 2 fois en passant par PAS DE > VERROU et la dernière fois par OK > En production cela ne fonctionnera pas car le Rollback annulera la > transaction avant d'être arrivé à terme. > > Je n'arrive pas à comprendre pourquoi il y a des activations qui ne > correspondent pas à ce que je souhaiterai ! > > > Merci de votre aide. > ac at expedito dot fr