IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Développement SQL Server Discussion :

trigger et INSERT INTO..SELECT


Sujet :

Développement SQL Server

  1. #1
    Membre du Club
    Profil pro
    Developper
    Inscrit en
    Juin 2008
    Messages
    55
    Détails du profil
    Informations personnelles :
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Developper

    Informations forums :
    Inscription : Juin 2008
    Messages : 55
    Points : 53
    Points
    53
    Par défaut trigger et INSERT INTO..SELECT
    Bonjour,

    j'ai un trigger sur insert dans sur une table lhisto.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
     
    ALTER TRIGGER [TRI_CalculStat] ON [dbo].[LHisto]
    AFTER INSERT AS
    	declare @idlhisto int
    	declare @CodeSociete int
    	declare @idUG int
    	declare @DateVente datetime
    	declare @CodeArticle int
    	declare @CodeReglement int
    	declare @pointSubvar int
     
    	set @idlhisto = -1
     
    	if not exists (Select UseTrigger FROM servicelanceur where UseTrigger =1) BEGIN
    		RETURN
    	END
     
        SELECT @idlhisto = i.idlhisto,  @CodeSociete = c.codesociete, @idUG = i.codeUG, @DateVente = i.datevente, @CodeArticle = codearticle, 
    	@CodeReglement = Codereglement, @pointSubvar = coalesce(pointsubvar,0)
    	FROM inserted as i  INNER JOIN CLient as c ON c.codeclient = i.codeclient AND c.affectation = i.affectation 
    	WHERE Typeligne = 1 AND codeevenement = 'VT' and (codeLot = 0 OR CodeLot = CodeArticle)	and (codemenu = 0 OR codemenu = codearticle)
    	AND (Saisiedirecte = 0 OR (saisiedirecte = 1 AND Codereglement NOT IN (8,11)))
     
    	IF @IdLhisto > 0 BEGIN
    		IF @pointSubvar = 0 BEGIN
    			IF @CodeReglement <> 8 AND @CodeReglement <> 11 BEGIN
     
    				exec Trigger_FactureAuto @idlhisto, @CodeSociete, @idUG, @DateVente, @CodeArticle
     
    			END
    			ELSE BEGIN
     
    				exec Trigger_FactureManuelle @Idlhisto
     
    			END
    		END
    		ELSE BEGIN
    			IF @CodeReglement <> 8 AND @CodeReglement <> 11 BEGIN
    				exec Trigger_FacturePointSubVar @Idlhisto
    			END
    		END
    	END
    j'ai 2000 Lignes dans ma table lhisto_temp

    j'exécute la requete suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    INSERT INTO LHisto (TypeLigne, CodeCaisse, CodeUD, CodeRU, CodeUG, CodeCrous, DateVente, CodeArticle, CodeEvenement, NumeroTicketCaisse, Ligne, Quantite, Prix, CodeReglement, Libelle1, Libelle2,
    Libelle3, Libelle4, Libelle5, CodeClient, Affectation, Cycle, Solde, NumeroTicketLie, CodeLot, CodeMenu, BadgeSociete, BadgeTarif, BadgeRegion, BadgeNom, BadgeValidite,
    BadgeCaution, BadgeFidelite, BadgeJetons, Taux_TVA, PrixHT, PartSociete, PartSocieteHTCalculee, NumCB, DateService, Service, UAIRne, Differe, NombrePoint, PointSubVar)
    SELECT TypeLigne, CodeCaisse, CodeUD, CodeRU, CodeUG, CodeCrous, DateVente, CodeArticle, CodeEvenement, NumeroTicketCaisse, Ligne, Quantite, Prix, CodeReglement, Libelle1, Libelle2,
    Libelle3, Libelle4, Libelle5, CodeClient, REPLACE(Affectation, 'IDT', '0'), Cycle, Solde, NumeroTicketLie, CodeLot, CodeMenu, BadgeSociete, BadgeTarif, BadgeRegion, BadgeNom, BadgeValidite,
    BadgeCaution, BadgeFidelite, BadgeJetons, Taux_TVA, PrixHT, PartSociete,  PartSociete,  NumCB, DateService, Service, UAIRne, Differe, NombrePoint, PointSubVar
    FROM LHisto_Temp, Vue_Lieux
    Mon trigger ne se déclenche pas ou plutôt, il se déclenche seulement pour la dernière ligne insérée...

    si je fais

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    INSERT INTO LHisto (TypeLigne, CodeCaisse, CodeUD, CodeRU, CodeUG, CodeCrous, DateVente, CodeArticle, CodeEvenement, NumeroTicketCaisse, Ligne, Quantite, Prix, CodeReglement, Libelle1, Libelle2,
    Libelle3, Libelle4, Libelle5, CodeClient, Affectation, Cycle, Solde, NumeroTicketLie, CodeLot, CodeMenu, BadgeSociete, BadgeTarif, BadgeRegion, BadgeNom, BadgeValidite,
    BadgeCaution, BadgeFidelite, BadgeJetons, Taux_TVA, PrixHT, PartSociete, PartSocieteHTCalculee, NumCB, DateService, Service, UAIRne, Differe, NombrePoint, PointSubVar)
    SELECT TypeLigne, CodeCaisse, CodeUD, CodeRU, CodeUG, CodeCrous, DateVente, CodeArticle, CodeEvenement, NumeroTicketCaisse, Ligne, Quantite, Prix, CodeReglement, Libelle1, Libelle2,
    Libelle3, Libelle4, Libelle5, CodeClient, REPLACE(Affectation, 'IDT', '0'), Cycle, Solde, NumeroTicketLie, CodeLot, CodeMenu, BadgeSociete, BadgeTarif, BadgeRegion, BadgeNom, BadgeValidite,
    BadgeCaution, BadgeFidelite, BadgeJetons, Taux_TVA, PrixHT, PartSociete,  PartSociete,  NumCB, DateService, Service, UAIRne, Differe, NombrePoint, PointSubVar
    FROM LHisto_Temp, Vue_Lieux
    WHERE codeclient = '127438' and typeligne = 1 and Ligne = 1
    qui ne renvoie qu'une seule ligne, alors il s'execute.

    Est ce que ça veux dire qu'un trigger sur insert ne fonctionne que pour les INSERT ligne par ligne ? ça ne fonctionne pas sur les INSERT... INTO ?
    Est ce que c'est parce que j'appelle d'autres procédures stockées dans mon trigger ?


    Merci

    [edit]

    En fait si je comprend bien mon trigger s'exécute après l'insert des 2000 lignes et pas ligne par ligne. Donc si jeux veux executer mon trigger ligne par ligne, il faut que je fasse un curseur sur la table inserted pour la passer ligne par ligne, c'est bien ça ?

    Merci

  2. #2
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 768
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 768
    Points : 52 577
    Points
    52 577
    Billets dans le blog
    5
    Par défaut
    C'est normal. Les déclencheurs sont ensembliste et ne se déclenchent qu'une seule fois quelque soit le nombre de ligne impactées par l'ordre sql qui l'a déclenché.
    Vous devez donc :
    • soit écrire du code purement ensembliste (requêtes SQL)
    • soit implémenter un curseur pour parcourir les lignes des pseudos tables.

    Bien évidemment c'est la solution 1 qui est à préférer dans tous les cas.

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  3. #3
    Membre du Club
    Profil pro
    Developper
    Inscrit en
    Juin 2008
    Messages
    55
    Détails du profil
    Informations personnelles :
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Developper

    Informations forums :
    Inscription : Juin 2008
    Messages : 55
    Points : 53
    Points
    53
    Par défaut
    Merci bien,

    Bon ben... curseur...
    J'en ai supprimé un bon nombre dans l'application, mais celui là, pas possible.

  4. #4
    Modérateur

    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Janvier 2005
    Messages
    5 826
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2005
    Messages : 5 826
    Points : 12 371
    Points
    12 371
    Par défaut
    Bonjour,

    Mettre un curseur dans un trigger ... ou comment se pourrir les performances

    Voyez plutôt quelles sont les procédures stockées qui dépendent de la table LHisto, et modifiez leur code pour qu'il soit purement ensembliste.
    Ou écriver une procédure un peu plus générique que Trigger_FactureAuto, Trigger_FacturePointSubVar et Trigger_FactureManuelle, et appelez-la dans celles-ci

    @++

  5. #5
    Membre du Club
    Profil pro
    Developper
    Inscrit en
    Juin 2008
    Messages
    55
    Détails du profil
    Informations personnelles :
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Developper

    Informations forums :
    Inscription : Juin 2008
    Messages : 55
    Points : 53
    Points
    53
    Par défaut
    Effectivement, un curseur dans un trigger doit en horrifier plus d'un... (désolé...) mais difficile d'être ensembliste sur mon traitement. Et de mon point du vue, on a un gain fabuleux de performances par rapport au traitement sans trigger !

    Même avec ce fichu curseur, la durée de l'insert avec trigger et sans trigger est quasi la même (j'ai testé avec 20.000 lignes ce qui correspond a une échelle haute de ce qui se produit quotidiennement sur les sites de production) et est très rapide entre 1 et 5 secondes.

    Or avant l'utilisation de ce trigger, pour arriver au même résultat (calcul de factures) , le traitement durait 10 minutes sur la même quantité de données.

  6. #6
    Modérateur

    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Janvier 2005
    Messages
    5 826
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2005
    Messages : 5 826
    Points : 12 371
    Points
    12 371
    Par défaut
    Bonjour,

    Cela est probablement du à l'utilisation de la table virtuelle INSERTED, qui utilise massivement la base de données TempDB (gestion des versions de ligne).
    Si de plus vous n'avez pas taillé TempDB proprement, cela oblige à un gonflement de la taille des fichiers, qui coûte très cher en ressources disque, qui lui-même coûte cher à SQL Server puisque les accès disques sont lents.

    Si vous nous donniez le code de votre curseur, nous pourrions le "transformer" en code purement ensembliste

    Regardez les écarts de temps d'exécution entre un curseur et une requête

    @++

  7. #7
    Membre du Club
    Profil pro
    Developper
    Inscrit en
    Juin 2008
    Messages
    55
    Détails du profil
    Informations personnelles :
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Developper

    Informations forums :
    Inscription : Juin 2008
    Messages : 55
    Points : 53
    Points
    53
    Par défaut
    Effectivement, la différence de durée d'exécution est impressionnante !
    Merci pour votre proposition de transformer mon curseur en code ensembliste, mais j'ai pas le courage de copier tout mon code (le trigger fait intervenir 5 procédures stockée selon la valeur de certaines colonnes)

    Cordialement

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. SQL : syntaxe insert into select
    Par chrislauxerrois dans le forum Access
    Réponses: 15
    Dernier message: 31/07/2006, 16h12
  2. [Oracle 9] Anomalie insert into select
    Par maxidoove dans le forum Langage SQL
    Réponses: 2
    Dernier message: 05/05/2006, 14h11
  3. probleme dans un INSERT INTO...........SELECT
    Par briiice dans le forum Requêtes
    Réponses: 5
    Dernier message: 26/01/2006, 15h13
  4. Incrémenter champ : insert into . select max(.) + 1 from .
    Par ludo.guy dans le forum Langage SQL
    Réponses: 10
    Dernier message: 25/11/2004, 14h39
  5. Erreur lors d'une requete insert into.. select
    Par Mr N. dans le forum MS SQL Server
    Réponses: 5
    Dernier message: 04/11/2004, 17h32

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo