2011-02-15 5 views
0

J'ai une table A (SQL Server 2008) qui contient des ensembles de nombres min et max. Dans l'une de mes procédures stockées, j'utilise cette table jointe à une table de produits B pour trouver un numéro de produit disponible compris entre min et max puis insérer un nouveau produit avec ce numéro de produit. Donc, je veux le prochain numéro gratuit qui est entre min/max. Entre la découverte du prochain numéro disponible et l'insertion de la ligne de produit, je veux un verrou pour empêcher quiconque de trouver le même nombre (et en donnant une copie).Comment verrouiller pour éviter les numéros en double

Comment devrais-je penser dans cette situation? Dois-je obtenir un verrou de mise à jour sur la table A même si je ne le modifie jamais? Le verrou doit être libéré après avoir fait l'insertion dans la table B et la transaction se termine? Cette fermeture de mise à jour empêchera-t-elle d'autres transactions de lire la table A?

Editer: La table min/max est une table pour différentes séries de produits. Selon la série que vous voulez, je veux essayer de trouver un numéro disponible dans cette séquence. Le productnr n'est pas unique, il serait possible de le rendre unique en combinaison avec une deuxième colonne. Simplifié sp:

CREATE PROCEDURE [dbo].[InsertProduct] 
(
@Param1 int, 
@Param2 bit, 
... 
@Param20 int) AS 
BEGIN 
    DECLARE @ProductNr int 
    --Here I do a query to determine which ProductNr I should have. Checking that the number is between max/min in the series and that no other product has this productnr. 
    --Now insert the row 
    INSERT INTO Products VALUES (@Param1, @ProductNr, ...., @Param2 
END 

Répondre

1

Votre question est un peu obscure, il serait utile si vous avez inclus des exemples de données. Quoi qu'il en soit, une tactique que j'ai utilisée dans le passé est d'essayer de tout emballer avec une seule instruction - ici, ce serait un INSERT. Chaque instruction SQL est de facto enveloppée dans sa propre transaction implicite (c'est l'atomicité, ce que le "A" dans l'ACID des propriétés de la base de données relationnelle renommée). Dans psuedo code, il avait l'air quelque chose comme:

INSERT MyTable (Id, Plus, Other, Columns) 
select CalcForNewId, Plus, Other, Columns 
from [what may be a pertty convoluted query to determine the "next" valid Id] 

Cela ne fonctionne que si vous pouvez écrire votre logique métier comme une seule requête raisonnable (où « raisonnable » signifie qu'il ne se verrouille pas, bloquer ou blocage soit le courant ou tout autre utilisateur pour une durée déraisonnable). Cela peut être une grosse commande, mais je prendrais cela pour avoir à écrire un code BEGIN TRANSACTION/COMMIT/ROLLBACK complexe mélangé avec TRY ... CATCH bloque n'importe quel jour. (Cela fonctionnera bien sûr, et j'ai mis @Scott Bruns en conséquence.)

+0

Ce serait probablement le meilleur moyen. Je ne peux pas avoir une contrainte unique sur la colonne nombre car elle peut contenir des valeurs nulles et sql server n'autorise pas une contrainte unique avec plusieurs valeurs nulles pour autant que je sache. – KTrum

+0

@KTrum - Vous pouvez créer une contrainte unique filtrée pour avoir la vérification unique tout en autorisant les valeurs nulles. 'create unique index Nom sur Tbl1 (Field asc) où (Field n'est pas nul)' –

1

Insérez simplement le numéro suivant dans la table B. S'il est validé, il est à votre disposition. Si vous obtenez une violation de clé, cela signifie qu'un processus différent vient d'entrer le nouveau numéro. Dans ce cas, incrémentez le nouveau numéro et réessayez.

La base de données traitera automatiquement la concertivité pour vous. Aucun verrouillage manuel n'est requis.

+0

Il n'y a pas d'identité dans la colonne. Dans certains cas, il peut y avoir des doublons. – KTrum

+0

Vous avez plusieurs produits dans la table des produits avec le même numéro de produit? –

+0

Oui, null. Ce n'est pas commun, mais il doit être possible d'avoir. Au moins dans ce scénario. – KTrum

Questions connexes