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 :

SqlBulkCopy & Trigger instead of INSERT


Sujet :

Développement SQL Server

  1. #1
    Futur Membre du Club
    Inscrit en
    Octobre 2008
    Messages
    14
    Détails du profil
    Informations forums :
    Inscription : Octobre 2008
    Messages : 14
    Points : 6
    Points
    6
    Par défaut SqlBulkCopy & Trigger instead of INSERT
    Bonjour a tous,

    Je tente (en vain, d'ou le post ) d'insérer des lignes dans ma base de données a partir de fichiers Excel en utilisant la méthode SqlBulkCopy.

    En fait mon fichier Excel est de la forme: fundID, name, currency, price; ou fundID est une clé etrangere sur la table Fund. Le problème, c'est que les utilisateurs sont amenés a uploadé un fichier Excel sans avoir préalablement créé le fundID.

    J'ai donc créé un TRIGGER INSTEAD OF INSERT qui vérifie que le fundID existe, et si ce n'est pas le cas, il le créé avant d'insérer la ligne qui y fait référence.
    Tout cela marche très bien quand j'insère une ligne directement dans SQL Server.

    Par contre, quand j'utilise la méthode SqlBulkCopy (qui fonctionne lorsque le trigger n'est pas présent), je rencontre une erreur.

    TRIGGER:
    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
     
    ALTER TRIGGER [CreateSubFundSEC]
    ON [dbo].[TB_PortfolioSec]
    INSTEAD OF INSERT
    AS
    BEGIN
     
    	IF NOT EXISTS (SELECT id FROM Fund WHERE (id = (SELECT FundID FROM inserted)))
    	BEGIN
    		INSERT INTO TB_Fund(id, createdBy, createdOn)
    			SELECT FundID, createdBy, createdOn
    			FROM inserted
    	END
     
     
    	INSERT INTO TB_PortfolioSec (FundID, ISIN, date, name, CCY, quantity, costBase, XRate, priceLocal, createdBy, createdOn)
    			SELECT  subFundID, ISIN, date, name, CCY, quantity, costBase, XRate, priceLocal, createdBy, createdOn
    			FROM inserted
    END

    Le problème vient de :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    IF NOT EXISTS (SELECT id FROM Fund WHERE (id = (SELECT FundID FROM inserted)))
    car je fais un = alors que SqlBulkCopy traite les lignes comme un seul bloc ??

    Il n'y aurait pas moyen de le forcer a faire du ligne a ligne ?

    J'espere que j'ai été plus ou moins clair... Sinon je preciserai !

    Merci a vous!!

  2. #2
    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,

    Vous demandez à votre trigger d'ajouter des lignes dans TbFund s'il existe des ID qui ne sont pas dans la table Fund.
    Or votre condition fonctionne dès lors qu'un seul des ID n'est pas dans Fund, ce qui marche très bien pour une ligne mais pas pour 100 000 par exemple.
    En plus comme vous n'avez pas mis de clause DISTINCT, si votre ID est plusieurs fois présent, vous allez tenter de l'insérer encore alors qu'il s'agit d'une clé primaire.

    Il vous faudrait donc écrire :

    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
    43
    44
    45
    ALTER TRIGGER [CreateSubFundSEC]
    	ON [dbo].[TB_PortfolioSec]
    INSTEAD OF INSERT
    AS
    BEGIN
    	-- Ajoute seulement les FundID dans TbFund qui n'existent pas
    	INSERT INTO Tb_Fund
    	(
    		id,
    		createdBy,
    		createdOn
    	)
    	SELECT DISTINCT FundID,
    			createdBy,
    			createdOn
    	FROM INSERTED
    	WHERE FundID NOT IN (SELECT ID FROM Fund)
     
    	INSERT INTO TB_PortfolioSec
    	(
    		FundID,
    		ISIN,
    		date,
    		name,
    		CCY,
    		quantity,
    		costBase,
    		XRate,
    		priceLocal,
    		createdBy,
    		createdOn
    	)
    	SELECT subFundID,
    		ISIN,
    		date,
    		name,
    		CCY,
    		quantity,
    		costBase,
    		XRate,
    		priceLocal,
    		createdBy,
    		createdOn
    	FROM inserted
    END
    Il n'y aurait pas moyen de le forcer a faire du ligne a ligne ?
    Si, avec des curseurs, mais c'est terriblement moins rapide que le code ensembliste.
    Les SGBDR sont conçus pour traiter des ensembles de données, pas pour faire du ligne à ligne, lent, moche et vieux comme COBOL, dont les curseurs sont issus.

    @++

  3. #3
    Futur Membre du Club
    Inscrit en
    Octobre 2008
    Messages
    14
    Détails du profil
    Informations forums :
    Inscription : Octobre 2008
    Messages : 14
    Points : 6
    Points
    6
    Par défaut
    Merci beaucoup pour la réponse rapide, je teste ca dès demain matin !

    En fait, j'avais vraiment le mauvais raisonnement, je me disais que le SGBD insert les lignes une après l'autre dans tous les cas... Apparement non ..

  4. #4
    Futur Membre du Club
    Inscrit en
    Octobre 2008
    Messages
    14
    Détails du profil
    Informations forums :
    Inscription : Octobre 2008
    Messages : 14
    Points : 6
    Points
    6
    Par défaut
    Ca marche a la perfection ! Merci encore.

    Pensez vous que ce genre de tests peut beaucoup ralentir les performances ou bien c'est tellement rapide que je ne le sentirai jamais, meme une fois que la base de données sera bien remplie?

    Je ne sais pas encore exactment combien de lignes comporteront mes tables Fund et Portfolio, sans doute plusieurs centaines de milliers a terme, pour la table portfolio en tout cas.

  5. #5
    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,

    Ravi de vous avoir dépanné

    Pensez vous que ce genre de tests peut beaucoup ralentir les performances ou bien c'est tellement rapide que je ne le sentirai jamais, même une fois que la base de données sera bien remplie?
    En fait tout dépend du cardinal du jeu de données.
    Tant que vous serez en phase de développement, donc avec un faible nombre de lignes, vous ne verrez peut-être pas la différence.
    En revanche dès que votre base de données aura commencé à vivre à son rythme de croisière, il en sera tout autrement, et je vous garantis qu'il va vous rester peu de cheveux parce que vous allez vous les arracher : vous allez avoir à vous amuser entre les blocages, les deadlocks et la lenteur de toutes les requêtes qui utiliseront cette table ...

    Je ne sais pas encore exactement combien de lignes comporteront mes tables Fund et Portfolio, sans doute plusieurs centaines de milliers a terme, pour la table portfolio en tout cas
    Je ne jure jamais du nombre de lignes d'une table, même si à priori je sais qu'il n'y en aura pas beaucoup.
    Je m'efforce d'écrire du code ensembliste : peut-être que quand je l'ecris je "perds" 5 minutes, mais le seul coup de maintenance que j'aurai est celui de l'introduction de nouvelles règles métier, et surtout des noeuds au cerveau en moins

    @++

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

Discussions similaires

  1. comment fonctionne trigger instead of insert ?
    Par 007007 dans le forum Langage SQL
    Réponses: 5
    Dernier message: 20/12/2009, 20h10
  2. trigger instead of insert
    Par smash dans le forum SQL Procédural
    Réponses: 1
    Dernier message: 26/08/2009, 20h07
  3. Création d'un trigger INSTEAD OF INSERT
    Par LestoK dans le forum Développement
    Réponses: 4
    Dernier message: 03/09/2008, 13h53
  4. Réponses: 32
    Dernier message: 21/08/2008, 12h27
  5. [SQL2K] TRIGGER - Instead of Insert
    Par buchette dans le forum Développement
    Réponses: 3
    Dernier message: 04/06/2008, 17h33

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