OVH Cloud OVH Cloud

Bien traiter les erreurs de doublon sur SQL Server

2 réponses
Avatar
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.

Selon vous laquel solution est la meilleure ?

--
Gilles TOURREAU
Responsable informatique
gilles.tourreau@pos.fr

Société P.O.S
Spécialiste en motoculture depuis + de 30 ans !
http://www.pos.fr

2 réponses

Avatar
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>
Avatar
MaXX
Patrick Mevzek wrote:
Le Fri, 18 Aug 2006 00:32:58 +0200, MaXX a écrit :
Je vois 2 solutions :






[snip 1 INSERT + gest. erreur]
[snip 2 SELECT avant INSEST]
Selon vous laquel solution est la meilleure ?


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