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 qui vérifie inscription à un groupe


Sujet :

Développement SQL Server

  1. #1
    Futur Membre du Club
    Inscrit en
    Mars 2011
    Messages
    3
    Détails du profil
    Informations forums :
    Inscription : Mars 2011
    Messages : 3
    Par défaut Trigger qui vérifie inscription à un groupe
    Bonjour, je souhaite créer un Trigger en SQL qui vérifie le nombre d'inscription maximal à un groupe précis(dans mon exemple, le maximum par groupe est de 4).

    Voici le code qui pose problème, car je peux entrer autant de membre que je veux dans un groupe :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    CREATE TRIGGER trigger_maximum_inscription
    ON tbl_inscription
    FOR INSERT AS
    DECLARE @nb_membre int, @no_groupe int
    SELECT @nb_membre=COUNT(no_membre)
    FROM tbl_inscription
    WHERE no_groupe = @no_groupe
    IF (@nb_membre>3)
    	BEGIN
    		RAISERROR('Le nombre de maximal(4) pour ce groupe est atteint', 16, 1)
    		ROLLBACK
    	END
    Merci de m'aider.. J'essais plein de choses, et ça ne semble pas fonctionner :-(

    P.S. Ma table inscription contient 2 variables et clés primaires --> no_membre et no_groupe

  2. #2
    Futur Membre du Club
    Inscrit en
    Mars 2011
    Messages
    3
    Détails du profil
    Informations forums :
    Inscription : Mars 2011
    Messages : 3
    Par défaut
    J'ai fait quelques modifications qui semblent fonctionner, mais je ne suis pas certain que ce code soit performant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    CREATE TRIGGER trigger_maximum_inscription
    	ON tbl_inscription
    	FOR INSERT AS
    	IF EXISTS(SELECT * FROM tbl_inscription
    		GROUP BY no_groupe
    		HAVING COUNT(*) > 4)
    	BEGIN
    		RAISERROR('Le nombre de maximal(4) pour ce groupe est atteint', 16, 1)
    		ROLLBACK
    	END
    GO

  3. #3
    Membre Expert Avatar de iberserk
    Homme Profil pro
    Architecte de base de données
    Inscrit en
    Novembre 2004
    Messages
    1 795
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Gironde (Aquitaine)

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

    Informations forums :
    Inscription : Novembre 2004
    Messages : 1 795
    Par défaut
    Vous vérifiez toute la table...
    Ne vérifiez la règle que pour les données insérées (table inserted...).

    exemple: vous ajoutez une ligne, vous n'avez à vérifier la règle que pour le no_groupe appartenant à la ligne insérée.

  4. #4
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    22 010
    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 : 22 010
    Billets dans le blog
    6
    Par défaut
    Ibersek à, raison, il faut faire comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    CREATE TRIGGER trigger_maximum_inscription
    ON tbl_inscription
    FOR INSERT AS
    IF EXISTS(SELECT * 
              FROM   tbl_inscription AS T
                     INNER JOIN inserted AS I
                           ON T.no_group = I.no_group
              GROUP BY no_groupe
              HAVING COUNT(*) > 4)
    BEGIN
       RAISERROR('Le nombre de maximal(4) pour ce groupe est atteint', 16, 1);
       ROLLBACK;
    END
    GO
    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/ * * * * *

  5. #5
    Membre Expert Avatar de iberserk
    Homme Profil pro
    Architecte de base de données
    Inscrit en
    Novembre 2004
    Messages
    1 795
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Gironde (Aquitaine)

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

    Informations forums :
    Inscription : Novembre 2004
    Messages : 1 795
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    CREATE TRIGGER trigger_maximum_inscription
    ON tbl_inscription
    FOR INSERT AS
    IF EXISTS(SELECT * 
              FROM   tbl_inscription AS T
                     INNER JOIN inserted AS I
                           ON T.no_group = I.no_group
              GROUP BY no_groupe
              HAVING COUNT(*) > 4)
    BEGIN
       RAISERROR('Le nombre de maximal(4) pour ce groupe est atteint', 16, 1);
       ROLLBACK;
    END
    GO

    Euh... cette syntaxe ne fonctionnera pas sous SQL SERVER, il faut préciser dans le select:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    CREATE TRIGGER trigger_maximum_inscription
    ON tbl_inscription
    FOR INSERT AS
    IF EXISTS(SELECT I.no_groupe
              FROM   tbl_inscription AS T
                     INNER JOIN inserted AS I
                           ON T.no_group = I.no_group
              GROUP BY I.no_groupe
              HAVING COUNT(*) > 4)
    BEGIN
       RAISERROR('Le nombre de maximal(4) pour ce groupe est atteint', 16, 1);
       ROLLBACK;
    END

  6. #6
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Par défaut
    Citation Envoyé par iberserk Voir le message
    Euh... cette syntaxe ne fonctionnera pas sous SQL SERVER, il faut préciser dans le select:
    Ha bon... pourquoi ?

    En effet, je pense qu'il faut préciser l'alias pour le GROUP BY et puis écrire no_groupe partout...

    Mais le "SELECT *" me semble tout à fait correct ?

  7. #7
    Membre Expert Avatar de iberserk
    Homme Profil pro
    Architecte de base de données
    Inscrit en
    Novembre 2004
    Messages
    1 795
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Gironde (Aquitaine)

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

    Informations forums :
    Inscription : Novembre 2004
    Messages : 1 795
    Par défaut
    Et pourtant non... testé sous SS 2008...
    Bizarrement avec le *, il dit que no_groupe est invalide dans la liste etc...

  8. #8
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Par défaut
    ne dit-il pas plutôt que le nom de colonne est invalide ?

    Dans la requete de SQLPro, et dans la tienne, c'est écrit no_group/no_groupe...

    comme je disais aussi, il manque un alias dans la group by, que tu as ajouté...

    Mais, je ne vois pas pourquoi le SELECT * serait incorrect, tant que la requête est bien dans un opérateur EXISTS
    Effectivement, la requête en elle même est incorrecte sinon, car toutes les colonnes ne sont pas dans le GROUP BY

  9. #9
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    22 010
    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 : 22 010
    Billets dans le blog
    6
    Par défaut
    Effectivement le SELECT * est incorrecte du fait du GROUP BY. Faites SELECT 0 SELECT 1 ou SELECT NULL !

    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/ * * * * *

  10. #10
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Par défaut
    pour ma part (SqlServer 2008) cela fonctionne :

    Code SQL : 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
     
     
     
    CREATE TABLE tbl_inscription(
    	no_membre INT NOT NULL,
    	no_groupe INT NOT NULL,
    	CONSTRAINT PK_tbl_inscription PRIMARY KEY CLUSTERED (no_membre, no_groupe)
    )
     
    GO 
     
    CREATE TRIGGER trigger_maximum_inscription
    ON tbl_inscription
    FOR INSERT AS
    IF EXISTS(SELECT *
              FROM   tbl_inscription AS T
                     INNER JOIN inserted AS I
                           ON T.no_groupe = I.no_groupe
              GROUP BY I.no_groupe
              HAVING COUNT(*) > 4)
    BEGIN
       RAISERROR('Le nombre de maximal(4) pour ce groupe est atteint', 16, 1);
       ROLLBACK;
    END

    Bizare...

    Mais dans tous les cas, il faudrait plutot écrire le trigger comme ceci :
    Code SQL : 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
     
    CREATE TRIGGER trigger_maximum_inscription
    ON tbl_inscription
    FOR INSERT AS
    	IF EXISTS(
    		SELECT *
    		FROM inserted AS I
    		WHERE (
    			SELECT COUNT(*) 
    			FROM tbl_inscription T 
    			WHERE  T.no_groupe = I.no_groupe
    		) > 4
    	)
    	BEGIN
    		RAISERROR('Le nombre de maximal(4) pour ce groupe est atteint', 16, 1);
    	ROLLBACK;
    END

    Afin de permettre les insertions multiples pour le même groupe, ce que le trigger avec jointure interdira pour plus de deux lignes...

  11. #11
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    291
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juillet 2005
    Messages : 291
    Par défaut
    Dans le même style j'ai un souci pour tester l'unicité d'un trigger
    Exemple

    J’ai une table avec Id, CC_Eu, CC_Us, on ne peut pas avoir de CC_EU dupliqué et CC_Us lorsqu’il y a un code.
    Exemple dans la table (test)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    ID	CC_EU	CC_US
    1	EU_01	Null
    2	EU_02	Null
    3	Null	CC_01
    4	Null	CC_03
    5	EU_09	CC_14
    Pour m’assurer, que les données sont bien uniques (CC_EU et CC_US) mais peuvent être dupliquer quand la valeur est à Null(Une cc peut ne pas exister US mais bien EU).

    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
    ALTER TRIGGER [dbo].[trigg_test]
    ON dbo.Test 
    FOR  INSERT
    AS 	
    	If (( Select count(*) 
               from inserted I inner join dbo.Test T on T on 
    I. CC_EU = T. CC_EU)>0)
    	Begin 
    		RAISERROR ('CC_EU Already exists', 16, 1)
    	End 
     
    	If (( Select count(*) 
               from inserted I inner join dbo.Test T on T on 
    I. CC_US = T. CC_US)>0)
    	Begin 
    		RAISERROR ('CC_US Already exists', 16, 1)
    	End
    Mais voilà, j’ai remarqué que dans la table dbo.Test la donnée existe déjà lorsque le trigger est appelé et donc avec mes conditions j’ai toujours une count(*)> 0(1). Et lorsque la donnée est dupliquée le count(*) est supérieur à 1. Donc j’ai changé dans le trigger les conditions en mettant >2. Mais est-ce correcte car je n’aime pas cette syntaxe.

    Il n’y a pas une autre méthode plus jolie ou efficace....


    Merci de votre aide

  12. #12
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Par défaut
    Bonjour,


    Si j'ai bien compris votre problème (CC_EU doit être NULL ou avoir une valeur unique, idem pour CC_US), il vous suffit d'un index unique filtrant les null sur chaque colonne

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    CREATE UNIQUE NONCLUSTERED INDEX UIX_CCEU
    ON test(CC_EU)
    WHERE CC_EU IS NOT NULL

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    CREATE UNIQUE NONCLUSTERED INDEX UIX_CCUS
    ON test(CC_US)
    WHERE CC_US IS NOT NULL

  13. #13
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    22 010
    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 : 22 010
    Billets dans le blog
    6
    Par défaut
    http://blog.developpez.com/sqlpro/p5...norme-sql-iso/

    Notamment index unique filtré !

    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/ * * * * *

  14. #14
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    291
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juillet 2005
    Messages : 291
    Par défaut
    Encore une fois j’admire la pertinence de vos réponses..
    Ps : si par hasard vous cherchez un boulot en Belgique ...... J'ai une bonne adresse pour vous ;-) ....

  15. #15
    Membre éprouvé

    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 448
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 448
    Par défaut
    Citation Envoyé par aieeeuuuuu Voir le message
    Bonjour,


    Si j'ai bien compris votre problème (CC_EU doit être NULL ou avoir une valeur unique, idem pour CC_US), il vous suffit d'un index unique filtrant les null sur chaque colonne

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    CREATE UNIQUE NONCLUSTERED INDEX UIX_CCEU
    ON test(CC_EU)
    WHERE CC_EU IS NOT NULL

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    CREATE UNIQUE NONCLUSTERED INDEX UIX_CCUS
    ON test(CC_US)
    WHERE CC_US IS NOT NULL
    Elle est sympa la version 2008 ^^

Discussions similaires

  1. Trigger qui vérifie l'insertion en base
    Par wapette21 dans le forum SQL Procédural
    Réponses: 6
    Dernier message: 21/10/2010, 10h08
  2. Trigger qui vérifie l'existence de fichiers
    Par roman67 dans le forum SQL
    Réponses: 22
    Dernier message: 10/02/2010, 10h37
  3. Site qui vérifie les actualisations d'une page web
    Par LFC dans le forum Autres langages pour le Web
    Réponses: 4
    Dernier message: 01/12/2005, 18h47
  4. [trigger] ... qui ne se déclenche pas
    Par bozo dans le forum MS SQL Server
    Réponses: 4
    Dernier message: 14/01/2004, 11h31
  5. Réponses: 5
    Dernier message: 25/11/2003, 09h41

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