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

MS SQL Server Discussion :

Vérifier doublons avant insertion (transaction, verrouillage et procédure stockée)


Sujet :

MS SQL Server

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre actif
    Inscrit en
    Janvier 2008
    Messages
    70
    Détails du profil
    Informations forums :
    Inscription : Janvier 2008
    Messages : 70
    Par défaut Vérifier doublons avant insertion (transaction, verrouillage et procédure stockée)
    Bonjour,


    Je veux (par exemple) tester si une personne existe déjà dans la base de données avant de l'insérer. Admettons que l'on fasse ce test par rapport au nom de la personne. On est dans une application multi-utilisateur.

    Je fais une transaction SQL dans une procédure stockée.

    pseudo code :

    1) Début Transaction
    2) declaration de @nbDoublon
    3) SELECT @nbDoublon = COUNT(*) FROM t_personne WHERE personne_nom='quelquun';
    4) IF @nbDoublon = 0 INSERT etc...
    5) Fin transaction

    Voici ma question :

    Si j'utilise l'isolation par défaut de SQL-SERVER (read commited) est ce qu'il n'y a pas un risque qu'entre l'étape 3 et 4 une requête concurrente s'insère et que donc j'insère un doublon ?

    En effet, le mode read commited ne vérouille pas les SELECT

    Faut il passer par un verouillage serializable ?

    N'y a t'il pas une autre solution ?

    - par exemple faire la verif dans la même instruction INSERT..

    - executer le select, le if et le insert via un sp_executesql (les intructions d'un sp_executesql sont ils exécutés en une seule fois cad pas de risque de requêtes concurrentes qui s'insèrent entre ses instructions ?)

    Si je passe par une transaction serializable, y a pas de soucis ? (à priori non mais ça fait toujorus peur ce genre de transactions)

  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
    22 006
    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 006
    Billets dans le blog
    6
    Par défaut
    Il faut au moins le niveau SERIALIZABLE.

    Mais je ne voit pas l'intérêt de faire cela en 2 ordres SQL avec une transaction.? Le mieux étant de le faire sans transaction en un seul ordre SQL :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    INSERT INTO MaTable
    SELECT 'Dupont'
    WHERE NOT EXISTS (SELECT *
                        FROM MaTable
                        WHERE Nom = 'Dupont')
    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 actif
    Inscrit en
    Janvier 2008
    Messages
    70
    Détails du profil
    Informations forums :
    Inscription : Janvier 2008
    Messages : 70
    Par défaut
    Bonjour SqlPro,

    Merci pour votre réponse.

    Il me manquait cette notion de NOT EXISTS merci !!

    Par contre, le fait de le gérer en deux requêtes, me permettrai par exemple de faire un RAISEERROR afin de récupérer l'erreur dans l'application (asp.net) et avertir l'utilisateur..

    Je ne me trompe pas ?

    P.S. : Pour la transaction, c'est par ce que je récupére l'id auto généré et j'insére des valeurs dans des relations.



    merci

  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 006
    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 006
    Billets dans le blog
    6
    Par défaut
    Pour l'erreur si pas d'insertion, interrogez le compteur de ligne dans votre L4G.

    Pour obtenir la clef autoincrémentée, utilisez la fonction SCOPE_IDENTITY() après l'insertion. Elle n'a pas à figurer dans la transaction.

    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 actif
    Inscrit en
    Janvier 2008
    Messages
    70
    Détails du profil
    Informations forums :
    Inscription : Janvier 2008
    Messages : 70
    Par défaut
    Merci !!

  6. #6
    Membre actif
    Inscrit en
    Juin 2008
    Messages
    26
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 26
    Par défaut Doublons...
    Bonjour,

    Je suis un peu dans le même cas (application multi-utilisateurs sous SQL2000) avec une table permettant de gérer un "compteur" que je récupère dans le code de mon application C#.

    Voici un extrait du contenu de ma procédure stockée :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    	
    	SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
    	BEGIN TRANSACTION;
    	IF 	((SELECT count(*) FROM [MaTable]) = 0)
    	BEGIN
    	/*(1)*/	SET @MaVariable = 1 ;
    	/*(2)*/	INSERT INTO [MaTable]([MonChamp]) VALUES(@MaVariable) ;
    	END
    	ELSE
    	BEGIN
    	/*(3)*/	SELECT @MaVariable = [MonChamp] + 1 FROM [MaTable]
    	/*(4)*/	UPDATE [MaTable] SET [MonChamp] = @MaVariable
    	END
    	COMMIT TRANSACTION;
    Apparemment, il arrive que cela me donne des doublons. Comment est-ce possible ?
    Imaginons que la procédure stockée soit appelée 2 fois quasi simultanément (donc 2 transactions X et Y), est-ce possible que la requête SELECT (N° 3) soit exécutée par X puis par Y et seulement ensuite que la requête UPDATE (N° 4) soit exécutée par X puis par Y ?

    Dans la clause "ELSE", j'avais pensé à passer la requête "UPDATE" avant le "SELECT".
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    UPDATE [MaTable] SET [MonChamp] = [MonChamp] + 1
    SELECT @MaVariable = [MonChamp] FROM [MaTable]
    Cela changerait-il quelque chose ?

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

Discussions similaires

  1. Vérifier données avant insertion dans une base de données
    Par massbbc dans le forum PHP & Base de données
    Réponses: 1
    Dernier message: 05/09/2010, 11h08
  2. Les transactions dans les procédures stockées
    Par CharleLéo dans le forum Connexion aux bases de données
    Réponses: 2
    Dernier message: 04/12/2009, 16h04
  3. vérifier si une table est vide avant insertion
    Par cashmoney dans le forum JDBC
    Réponses: 7
    Dernier message: 21/04/2009, 17h54
  4. [MySQL] Vérifier l'existance d'une donnée dans la base avant insertion
    Par Him dans le forum PHP & Base de données
    Réponses: 26
    Dernier message: 16/07/2006, 15h47
  5. [MySQL] Vérification de doublons avant insertion
    Par Nicos77 dans le forum PHP & Base de données
    Réponses: 15
    Dernier message: 09/12/2005, 13h37

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