2010-04-07 3 views
4

J'utilise Microsoft SQL Server et j'ai un scénario maître-détail dans lequel j'ai besoin de stocker l'ordre des détails. Donc, dans le tableau des détails, j'ai ID, MasterID, Position et d'autres colonnes. Il existe également un index unique sur MasterID et Position. Cela fonctionne bien sauf un cas: quand j'ai des détails existants et que je change d'ordre. Par exemple quand je change un détail sur la position 3 avec un détail sur la position 2. Quand je sauvegarde le détail sur la position 2 (qui dans la base de données a la position égale à 3) SQL Server proteste, parce que la contrainte d'unicité d'index.Mise à jour de plusieurs lignes qui sont en conflit avec l'index unique

Comment résoudre ce problème de manière raisonnable?

Nous vous remercions à l'avance
Lukasz Glaz

Répondre

1

Ceci est un problème classique et la réponse est simple: si vous voulez déplacer l'élément 3 en position 2, vous devez d'abord changer la colonne de tri de 2 en un nombre temporaire (par exemple 99). Donc, il va comme ceci:

Move 2 to 99 
Move 3 to 2 
Move 99 to 3 

Vous devez être prudent, cependant, que votre valeur temporaire est jamais utilisé dans le traitement normal et que vous respectez plusieurs threads le cas échéant.

Mise à jour: BTW - une façon de traiter avec les « utilisateurs multiples peut changer l'ordre » problème est de faire ce que je fais: donner à chaque utilisateur un ID numberical puis ajouter ceci au numéro temporaire (mon personnel ID est en fait l'ID du champ Identité unique de la table de personnel utilisée pour ouvrir les connexions). Ainsi, par exemple, si vos positions ne seront jamais négatives, vous pouvez utiliser -1000 - UserID comme valeur temporaire. Croyez-moi sur une chose cependant: vous faites pas voulez juste supposer que vous n'aurez jamais une collision. Si vous pensez que cela et fait se produisent, il sera extrêmement difficile de déboguer! GUZ signale que ses utilisateurs ont peut-être réorganisé un ensemble d'éléments de campagne et les ont soumis en tant que lot. Il ne s'agit pas simplement d'un changement de deux enregistrements. Vous pouvez aborder cela de deux façons, alors. Tout d'abord, vous pouvez changer les champs de tri existants de l'ensemble en un nouvel ensemble de valeurs non-collision (par exemple -100 - (staffID * maxSetSize) + existingOrderVal), puis enregistrez chaque enregistrement et changez chaque enregistrer à la nouvelle valeur de la commande. Ou vous pourriez essentiellement le traiter comme un tri à bulles sur un tableau où la valeur orderVal est l'équivalent de votre index de tableau. Soit cela vous semble logique (et c'est évident), soit vous devez vous en tenir à la solution 1 (ce qui est plus facile dans tous les cas).

+0

J'étais sur le point de poster cette réponse. Battez-moi par 30 (ish) secondes. – AllenG

+0

@AllenG - Je vous entends ... Je ne peux pas vous dire combien de fois j'ai appuyé sur le bouton Soumettre seulement pour trouver que j'ai été battu au coup de poing. Il y a un peu de pression sur le SO. –

+0

Le problème est qu'un utilisateur peut faire de nombreux changements dans la portée de l'ordre des détails, puis ces modifications sont enregistrées dans un lot. – GUZ

0

vous pouvez simplement supprimer la contrainte unique (mais laisser une clé d'index) sur la colonne de commande, et d'assurer l'unicité dans votre code si nécessaire.

+0

Venant d'un environnement EDI, je peux dire que ce n'est pas toujours pratique. Cela fonctionnerait normalement, mais il y a des cas où c'est beaucoup plus de problèmes que ça en vaut la peine. La solution de Mark fonctionne très bien. – AllenG

Questions connexes