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 :

fonction exists toujours vrai transact sql


Sujet :

Développement SQL Server

  1. #1
    Membre averti
    Homme Profil pro
    Freelance
    Inscrit en
    Février 2008
    Messages
    312
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Freelance

    Informations forums :
    Inscription : Février 2008
    Messages : 312
    Points : 390
    Points
    390
    Par défaut fonction exists toujours vrai transact sql
    bonjour a tous

    voila j'ai un trigger sur l'insertion dans une table ligne composé d'un numéro et d'un nom
    ce trigger me permet de vérifier si le nom existe déja dans la base et annule l'opération si oui
    pour cela je fait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    ALTER TRIGGER [dbo].[insertligne]
       ON  [dbo].[LIGNE]
       for insert
    AS 
    BEGIN
    	-- SET NOCOUNT ON added to prevent extra result sets from
    	-- interfering with SELECT statements.
    	SET NOCOUNT ON;
    if (exists(select INSERTED.libelle_ligne from ligne, INSERTED where ligne.libelle_ligne=INSERTED.libelle_ligne))
    begin
    	ROLLBACK
        RAISERROR 13000 'le nom ou le numéro de cette ligne existe déja' 
    end
    Le problème est que meme lorsque le nom n'est pas dans la base, il me sort l'erreur. Je ne voit vraiment pas de quoi cela peu venir
    N'hesitez pas a me demander plus de précisions
    merci d'avance pour vos réponses

  2. #2
    Membre actif
    Inscrit en
    Février 2009
    Messages
    224
    Détails du profil
    Informations forums :
    Inscription : Février 2009
    Messages : 224
    Points : 269
    Points
    269
    Par défaut
    Bonjour,

    Les déclencheurs SQL server soont en mode AFTER lors de son exécution la ligne est déjà présenta dans la table cible.
    La table inserted contient une "copie" des lignes insérées il est donc normal qu'EXIST retourne toujours VRAI

  3. #3
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 922
    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 922
    Points : 51 717
    Points
    51 717
    Billets dans le blog
    6
    Par défaut
    j'ai un trigger sur l'insertion dans une table ligne composé d'un numéro et d'un nom ce trigger me permet de vérifier si le nom existe déja dans la base et annule l'opération
    Il serait plus simple, mille fois plus performant et plus judicieux d'utiliser pour ce faire une contrainte d'unicité !

    A +

  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 : 43
    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,

    Voici ce que vous pouvez faire souhaitez insérer seulement les libelle_ligne qui ne sont pas déjà dans la table tout en insérant ce qui n'y sont pas déjà, et en vous signalant ceux qui y sont déjà :

    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
    ALTER TRIGGER TR_IOF_LIGNE
    	ON dbo.Ligne
    INSTEAD OF INSERT
    AS
    BEGIN
    	INSERT INTO dbo.Ligne
    			SELECT libelle_ligne
    			FROM INSERTED
    		EXCEPT 
    			SELECT libelle_ligne
    			FROM dbo.Ligne
     
    	DECLARE @Msg VARCHAR(512)
    	SELECT @Msg = ISNULL(@Msg, '') + CAST(libelle_ligne AS VARCHAR) + ', '
    	FROM dbo.Ligne AS L
    	JOIN INSERTED AS I ON L.libelle_ligne = I.libelle_ligne
     
    	IF @Msg IS NOT NULL
    	BEGIN
    		RAISERROR('Les libellés de ligne %s sont déjà stockés dans dbo.Ligne', 16, 1, @Msg)
    	END
    END
    Si en revanche votre INSERT comporte plusieurs colonnes, vous pouvez écrire dès SQL Server 2005 :

    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
     
    ALTER TRIGGER TR_IOF_LIGNE
    	ON dbo.Ligne
    INSTEAD OF INSERT
    AS
    BEGIN
    	WITH
    		CTE AS
    		(
    				SELECT libelle_ligne
    				FROM INSERTED
    			EXCEPT 
    				SELECT libelle_ligne
    				FROM dbo.Ligne
    		)
    	INSERT INTO dbo.Ligne
    	SELECT INSERTED.libelle_ligne,
    			INSERTED.maColonne0,
    			INSERTED.[...],
    			INSERTED.maColonneN
    	FROM CTE 
    	JOIN INSERTED ON CTE.libelle_ligne = INSERTED.libelle_ligne
     
    	DECLARE @Msg VARCHAR(512)
    	SELECT @Msg = ISNULL(@Msg, '') + CAST(libelle_ligne AS VARCHAR) + ', '
    	FROM dbo.Ligne AS L
    	JOIN INSERTED AS I ON L.libelle_ligne = I.libelle_ligne
     
    	IF @Msg IS NOT NULL
    	BEGIN
    		RAISERROR('Les libellés de ligne %s sont déjà stockés dans dbo.Ligne', 16, 1, @Msg)
    	END
    END
    et dès SQL Server 2000 :

    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
    ALTER TRIGGER TR_IOF_LIGNE
    	ON dbo.Ligne
    INSTEAD OF INSERT
    AS
    BEGIN
    	INSERT INTO dbo.Ligne
    	SELECT INSERTED.libelle_ligne,
    			INSERTED.maColonne0,
    			INSERTED.[...],
    			INSERTED.maColonneN
    	FROM (
    				SELECT libelle_ligne
    				FROM INSERTED
    			EXCEPT 
    				SELECT libelle_ligne
    				FROM dbo.Ligne
    		) TMP
    	JOIN INSERTED ON TMP.libelle_ligne = INSERTED.libelle_ligne
     
    	DECLARE @Msg VARCHAR(512)
    	SELECT @Msg = ISNULL(@Msg, '') + CAST(libelle_ligne AS VARCHAR) + ', '
    	FROM dbo.Ligne AS L
    	JOIN INSERTED AS I ON L.libelle_ligne = I.libelle_ligne
     
    	IF @Msg IS NOT NULL
    	BEGIN
    		RAISERROR('Les libellés de ligne %s sont déjà stockés dans dbo.Ligne', 16, 1, @Msg)
    	END
    END
    ou encore :

    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
    ALTER TRIGGER TR_IOF_LIGNE
    	ON dbo.Ligne
    INSTEAD OF INSERT
    AS
    BEGIN
    	INSERT INTO dbo.Ligne
    	SELECT INSERTED.libelle_ligne,
    			INSERTED.maColonne0,
    			INSERTED.[...],
    			INSERTED.maColonneN
    	FROM INSERTED
    	WHERE libelle_ligne NOT IN (
    									SELECT libelle_ligne
    									FROM dbo.Ligne
    								)
     
    	DECLARE @Msg VARCHAR(512)
    	SELECT @Msg = ISNULL(@Msg, '') + CAST(libelle_ligne AS VARCHAR) + ', '
    	FROM dbo.Ligne AS L
    	JOIN INSERTED AS I ON L.libelle_ligne = I.libelle_ligne
     
    	IF @Msg IS NOT NULL
    	BEGIN
    		RAISERROR('Les libellés de ligne %s sont déjà stockés dans dbo.Ligne', 16, 1, @Msg)
    	END
    END
    Mais il est clair que comme vous le dit SQLPro une contrainte d'unicité vous permet de faire cela sans un trigger, qui est gourmand en ressources :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ALTER TABLE dbo.Ligne
    ADD CONSTRAINT UQ_Ligne_libelle_ligne UNIQUE (libelle_ligne)
    Comme la création d'une contrainte d'unicité entraîne implicitement la créatin d'un index, vous y gagnerez même peut-être un peu lors de vos recherche sur la colonne libelle_ligne

    @++

  5. #5
    Membre averti
    Homme Profil pro
    Freelance
    Inscrit en
    Février 2008
    Messages
    312
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Freelance

    Informations forums :
    Inscription : Février 2008
    Messages : 312
    Points : 390
    Points
    390
    Par défaut
    merci a tous pour vos réponse

    Il s'est avéré que mon problème venait du for ligne, que j'ai remplacé par instead of ligne, je croyai pourtant que l'instruction for signalait qu'il fallait far le test avant l'opération
    Sinon pour l'unicité j'y avais pensé mais le problème est que j'ai une multitude de triggers qui me renvoie un message d'erreur, et je me sert de ces messages d'erreurs pour les afficher dans une application, quelle sera le message d'erreur renvoyé par sql serveur automatiquement?, il faut qu'il soit clair pour l'utilisateur
    Sinon elsuket je ne connait pas cette syntaxe en sql
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    CTE AS
    		(
    				SELECT libelle_ligne
    				FROM INSERTED
    			EXCEPT 
    				SELECT libelle_ligne
    				FROM dbo.Ligne
    		)
    pourrai m'en dire plus,a quoi ca sert,...
    j'attend ta réponse et je met résolu

  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 : 43
    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,

    Voici un très bon tutoriel de SQLPro à ce sujet, et la documentation de MS ici.

    Utiliser une expression de table commune non récursive aboutit au même plan de requête que la requête qui est juste en dessous dans ma réponse précédente.

    Le message que reçoit l'utilisateur lors d'une violation de clé unique est :

    Msg*2627, Niveau*14, État*1, Ligne*1
    Violation de la contrainte UNIQUE KEY 'UQ_nomContrainte'. Impossible d'insérer une clé en double dans l'objet 'monSchema.maTable'.
    L'instruction a été arrêtée.
    @++

  7. #7
    Membre averti
    Homme Profil pro
    Freelance
    Inscrit en
    Février 2008
    Messages
    312
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Freelance

    Informations forums :
    Inscription : Février 2008
    Messages : 312
    Points : 390
    Points
    390
    Par défaut
    merci
    Je crois que j'ai du boulot car j'ai encore jamais utilisé les récursives
    sinon pour le message d'erreur il est pas super clair je vais garder ma solution
    le sujet est clos

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

Discussions similaires

  1. [2008] Tester l'existence d'une fonction en Transact SQL
    Par bza88 dans le forum MS SQL Server
    Réponses: 6
    Dernier message: 20/11/2014, 18h09
  2. fonction VBA - fonction transact SQL
    Par roblescriso dans le forum VBA Access
    Réponses: 7
    Dernier message: 13/02/2008, 17h17
  3. Utilisation d'une fonction Transact-SQL ds une requête SQL
    Par Fl0ppeur dans le forum Langage SQL
    Réponses: 1
    Dernier message: 21/02/2006, 14h42
  4. - fonction Transact-SQL...
    Par korrigann dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 22/05/2003, 16h00

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