Bien traiter les erreurs de doublon sur SQL Server
2 réponses
Gilles TOURREAU
Bonjour,
J'ai plusieurs contraintes UNIQUE dans différentes tables de ma base de
données. Cela pour éviter d'avoir des informations en doubles
(références en stock, ...etc).
J'ai une application qui demande à l'utilisateur de saisir des
informations à l'écran.
Je voudrais savoir comment gérer et prévenir l'utilisateur que les
informations qu'il a saisie existe déjà...
Je vois 2 solutions :
- Soit faire un INSERT et traiter les exceptions généré par SQL Server.
Si par exemple l'erreur n°2627 est déclenché (Violation d'une
contrainte) je dis alors à l'utilisateur de saisir autre chose !
- Ou alors je fais un SELECT avant le INSERT pour voir si ce que
l'utilisateur a saisie n'existe pas.
Cette action est irreversible, confirmez la suppression du commentaire ?
Signaler le commentaire
Veuillez sélectionner un problème
Nudité
Violence
Harcèlement
Fraude
Vente illégale
Discours haineux
Terrorisme
Autre
Patrick Mevzek
Le Fri, 18 Aug 2006 00:32:58 +0200, MaXX a écrit :
Je vois 2 solutions : - Soit faire un INSERT et traiter les exceptions généré par SQL Server. Si par exemple l'erreur n°2627 est déclenché (Violation d'une contrainte) je dis alors à l'utilisateur de saisir autre chose ! - Ou alors je fais un SELECT avant le INSERT pour voir si ce que l'utilisateur a saisie n'existe pas. Selon vous laquel solution est la meilleure ?
Personnellement, je choisirais la seconde, je la trouve plus propre, et elle peut éviter des petits problèmes dans certains cas [*].
Personnellement je pense que ca dépend :-) Déjà de la probabilité que le clash arrive, donc si on penche du côté optimiste (on ne vérifie qu'après coup si clash) ou pessimiste (on vérifie systématiquement). On peut baisser la probabilité qu'un clash existe (mais pas l'annuler) en présentation à l'utilisateur, non pas un champ vide à remplir, mais une liste déroulante ou équivalent avec les choix dans la base. Donc après ca dépend beaucoup des masques de saisie présentés à l'utilisateur.
[*] Un exemple avec postgresql, les séquences est sont incrémentées systématiquement que la transaction aboutisse ou non, pour éviter de générer la même valeur dans deux transactions différentes. Ca peut être gènant si on a besoin d'une numérotation "sans trous".
C'est «by design».
On doit retrouver ça d'une façon ou d'une autre dans d'autres SGBDR. Le SELECT devrait minimiser les chances de tomber dans ce piége à cause d'un champ oublié.
Sauf, qu'à part faire attention aux niveaux d'isolation (on est dans une transaction bien entendu), il peut y avoir une création après le SELECT et avant l'insertion, d'où échec de la contrainte d'unicité.
-- Patrick Mevzek . . . . . . Dot and Co (Paris, France) <http://www.dotandco.net/> <http://www.dotandco.com/> <http://www.dotandco.net/ressources/icann_registrars/TLD>
Le Fri, 18 Aug 2006 00:32:58 +0200, MaXX a écrit :
Je vois 2 solutions :
- Soit faire un INSERT et traiter les exceptions généré par SQL Server.
Si par exemple l'erreur n°2627 est déclenché (Violation d'une
contrainte) je dis alors à l'utilisateur de saisir autre chose !
- Ou alors je fais un SELECT avant le INSERT pour voir si ce que
l'utilisateur a saisie n'existe pas.
Selon vous laquel solution est la meilleure ?
Personnellement, je choisirais la seconde, je la trouve plus propre, et
elle peut éviter des petits problèmes dans certains cas [*].
Personnellement je pense que ca dépend :-)
Déjà de la probabilité que le clash arrive, donc si on penche du côté
optimiste (on ne vérifie qu'après coup si clash) ou pessimiste (on
vérifie systématiquement).
On peut baisser la probabilité qu'un clash existe (mais pas l'annuler) en
présentation à l'utilisateur, non pas un champ vide à remplir, mais une
liste déroulante ou équivalent avec les choix dans la base.
Donc après ca dépend beaucoup des masques de saisie présentés à
l'utilisateur.
[*] Un exemple avec postgresql, les séquences est sont incrémentées
systématiquement que la transaction aboutisse ou non, pour éviter de
générer la même valeur dans deux transactions différentes. Ca peut
être gènant si on a besoin d'une numérotation "sans trous".
C'est «by design».
On doit retrouver ça d'une façon ou d'une autre dans d'autres SGBDR.
Le SELECT devrait minimiser les chances de tomber dans ce piége à cause
d'un champ oublié.
Sauf, qu'à part faire attention aux niveaux d'isolation (on est dans une
transaction bien entendu), il peut y avoir une création après le SELECT
et avant l'insertion, d'où échec de la contrainte d'unicité.
--
Patrick Mevzek . . . . . . Dot and Co (Paris, France)
<http://www.dotandco.net/> <http://www.dotandco.com/>
<http://www.dotandco.net/ressources/icann_registrars/TLD>
Le Fri, 18 Aug 2006 00:32:58 +0200, MaXX a écrit :
Je vois 2 solutions : - Soit faire un INSERT et traiter les exceptions généré par SQL Server. Si par exemple l'erreur n°2627 est déclenché (Violation d'une contrainte) je dis alors à l'utilisateur de saisir autre chose ! - Ou alors je fais un SELECT avant le INSERT pour voir si ce que l'utilisateur a saisie n'existe pas. Selon vous laquel solution est la meilleure ?
Personnellement, je choisirais la seconde, je la trouve plus propre, et elle peut éviter des petits problèmes dans certains cas [*].
Personnellement je pense que ca dépend :-) Déjà de la probabilité que le clash arrive, donc si on penche du côté optimiste (on ne vérifie qu'après coup si clash) ou pessimiste (on vérifie systématiquement). On peut baisser la probabilité qu'un clash existe (mais pas l'annuler) en présentation à l'utilisateur, non pas un champ vide à remplir, mais une liste déroulante ou équivalent avec les choix dans la base. Donc après ca dépend beaucoup des masques de saisie présentés à l'utilisateur.
[*] Un exemple avec postgresql, les séquences est sont incrémentées systématiquement que la transaction aboutisse ou non, pour éviter de générer la même valeur dans deux transactions différentes. Ca peut être gènant si on a besoin d'une numérotation "sans trous".
C'est «by design».
On doit retrouver ça d'une façon ou d'une autre dans d'autres SGBDR. Le SELECT devrait minimiser les chances de tomber dans ce piége à cause d'un champ oublié.
Sauf, qu'à part faire attention aux niveaux d'isolation (on est dans une transaction bien entendu), il peut y avoir une création après le SELECT et avant l'insertion, d'où échec de la contrainte d'unicité.
-- Patrick Mevzek . . . . . . Dot and Co (Paris, France) <http://www.dotandco.net/> <http://www.dotandco.com/> <http://www.dotandco.net/ressources/icann_registrars/TLD>
MaXX
Patrick Mevzek wrote:
Le Fri, 18 Aug 2006 00:32:58 +0200, MaXX a écrit :
Personnellement, je choisirais la seconde, je la trouve plus propre, e t elle peut éviter des petits problèmes dans certains cas [*].
Personnellement je pense que ca dépend :-) Déjà de la probabilité que le clash arrive, donc si on penche du côté optimiste (on ne vérifie qu'après coup si clash) ou pessimiste (on vérifie systématiquement).
J'ai tendance à utiliser la methode pessimiste là où je pense que j e peux (pourrais) avoir un clash. Le PO me semble considérer que la probabilité d'un clash est non négligeable.
On peut baisser la probabilité qu'un clash existe (mais pas l'annuler ) en présentation à l'utilisateur, non pas un champ vide à remplir, ma is une liste déroulante ou équivalent avec les choix dans la base. Donc après ca dépend beaucoup des masques de saisie présentés à l'utilisateur.
Le développeur doit faire sa part du boulot côté client pour respec ter les contraintes de la base (unique, not null, charactères autorisés, contraintes liées à l'activité ou au bon sens,...).
[*] Un exemple avec postgresql, les séquences est sont incrémenté es systématiquement que la transaction aboutisse ou non, pour éviter de générer la même valeur dans deux transactions différentes. Ca peut être gènant si on a besoin d'une numérotation "sans trous".
C'est «by design».
On doit retrouver ça d'une façon ou d'une autre dans d'autres SGBD R. Le SELECT devrait minimiser les chances de tomber dans ce piége à cause d'un champ oublié.
Sauf, qu'à part faire attention aux niveaux d'isolation (on est dans une transaction bien entendu), il peut y avoir une création après le SE LECT et avant l'insertion, d'où échec de la contrainte d'unicité.
Oui, d'où l'emploi de "minimiser"... Au pire, et seulement si ça se justifie, il reste la solution radicale du verou exclusif, avec tout les problèmes que ca comporte.
2c, -- MaXX
Patrick Mevzek wrote:
Le Fri, 18 Aug 2006 00:32:58 +0200, MaXX a écrit :
Personnellement, je choisirais la seconde, je la trouve plus propre, e t
elle peut éviter des petits problèmes dans certains cas [*].
Personnellement je pense que ca dépend :-)
Déjà de la probabilité que le clash arrive, donc si on penche du côté
optimiste (on ne vérifie qu'après coup si clash) ou pessimiste (on
vérifie systématiquement).
J'ai tendance à utiliser la methode pessimiste là où je pense que j e
peux (pourrais) avoir un clash. Le PO me semble considérer que la
probabilité d'un clash est non négligeable.
On peut baisser la probabilité qu'un clash existe (mais pas l'annuler ) en
présentation à l'utilisateur, non pas un champ vide à remplir, ma is une
liste déroulante ou équivalent avec les choix dans la base.
Donc après ca dépend beaucoup des masques de saisie présentés à
l'utilisateur.
Le développeur doit faire sa part du boulot côté client pour respec ter
les contraintes de la base (unique, not null, charactères autorisés,
contraintes liées à l'activité ou au bon sens,...).
[*] Un exemple avec postgresql, les séquences est sont incrémenté es
systématiquement que la transaction aboutisse ou non, pour éviter de
générer la même valeur dans deux transactions différentes. Ca peut
être gènant si on a besoin d'une numérotation "sans trous".
C'est «by design».
On doit retrouver ça d'une façon ou d'une autre dans d'autres SGBD R.
Le SELECT devrait minimiser les chances de tomber dans ce piége à cause
d'un champ oublié.
Sauf, qu'à part faire attention aux niveaux d'isolation (on est dans une
transaction bien entendu), il peut y avoir une création après le SE LECT
et avant l'insertion, d'où échec de la contrainte d'unicité.
Oui, d'où l'emploi de "minimiser"... Au pire, et seulement si ça se
justifie, il reste la solution radicale du verou exclusif, avec tout les
problèmes que ca comporte.
Personnellement, je choisirais la seconde, je la trouve plus propre, e t elle peut éviter des petits problèmes dans certains cas [*].
Personnellement je pense que ca dépend :-) Déjà de la probabilité que le clash arrive, donc si on penche du côté optimiste (on ne vérifie qu'après coup si clash) ou pessimiste (on vérifie systématiquement).
J'ai tendance à utiliser la methode pessimiste là où je pense que j e peux (pourrais) avoir un clash. Le PO me semble considérer que la probabilité d'un clash est non négligeable.
On peut baisser la probabilité qu'un clash existe (mais pas l'annuler ) en présentation à l'utilisateur, non pas un champ vide à remplir, ma is une liste déroulante ou équivalent avec les choix dans la base. Donc après ca dépend beaucoup des masques de saisie présentés à l'utilisateur.
Le développeur doit faire sa part du boulot côté client pour respec ter les contraintes de la base (unique, not null, charactères autorisés, contraintes liées à l'activité ou au bon sens,...).
[*] Un exemple avec postgresql, les séquences est sont incrémenté es systématiquement que la transaction aboutisse ou non, pour éviter de générer la même valeur dans deux transactions différentes. Ca peut être gènant si on a besoin d'une numérotation "sans trous".
C'est «by design».
On doit retrouver ça d'une façon ou d'une autre dans d'autres SGBD R. Le SELECT devrait minimiser les chances de tomber dans ce piége à cause d'un champ oublié.
Sauf, qu'à part faire attention aux niveaux d'isolation (on est dans une transaction bien entendu), il peut y avoir une création après le SE LECT et avant l'insertion, d'où échec de la contrainte d'unicité.
Oui, d'où l'emploi de "minimiser"... Au pire, et seulement si ça se justifie, il reste la solution radicale du verou exclusif, avec tout les problèmes que ca comporte.