2009-12-23 5 views
2

Si je veux sélectionner tous les enregistrements dans une table qui ne sont pas encore traitées, puis mettre à jour ces dossiers afin de tenir compte qu'ils ont été traités, je voudrais faire ce qui suit:transactions T-SQL et le verrouillage de table

SELECT * FROM [dbo].[MyTable] WHERE [flag] IS NULL; 
UPDATE [dbo].[MyTable] SET [flag] = 1 WHERE [flag] IS NULL; 

Comment m'assurer que UPDATE ne fonctionne que sur les enregistrements que je viens de sélectionner, c'est-à-dire empêcher la mise à jour des enregistrements ajoutés avec [flag] = NULL après mon SELECT mais avant mon UPDATE par un autre processus? Puis-je envelopper ces deux déclarations dans une transaction? Dois-je mettre un verrou sur la table?

Répondre

6

Appel unique, aucune transaction nécessaire à l'aide de la clause OUTPUT.

XLOCK verrouille exclusivement les lignes d'arrêter lit en même temps (par exemple, un autre processus à la recherche de lignes NULL)

UPDATE dbo.MyTable WITH (XLOCK) 
SET flag = 1 
OUTPUT INSERTED.* 
WHERE flag IS NULL; 
+1

Quelle est la première version de SQL Server qui prend en charge la clause 'OUTPUT'? –

+1

SQL Server 2005, ce qui devrait être une hypothèse juste à faire dans (presque) 2010 ... – gbn

+0

..et donné OP utilise SSIS aussi, basé sur d'autres questions. – gbn

2

Vous pouvez placer ces deux instructions dans une transaction avec read_committed ou une portée plus restreinte. C'est un peu cher et pourrait causer d'autres problèmes. La solution de King est plus réalisable.

3

Utilisation:

SELECT * 
    FROM [dbo].[MyTable] (UPDLOCK) 
WHERE [flag] IS NULL; 

UPDATE [dbo].[MyTable] 
    SET [flag] = 1 
WHERE [flag] IS NULL; 

Pour plus d'informations sur des notes de verrouillage:

+1

+1. Notez que cela doit être dans une transaction pour que le verrou de mise à jour soit transmis à l'instruction update. – womp

+0

Toujours 2 instructions qui ne sont pas nécessaires avec SQL Server 2005 + – gbn

5

Utilisez la clause SORTIE pour retourner un jeu de résultats à la mise à lui-même :

UPDATE [dbo].[MyTable] 
SET [flag] = 1 
OUTPUT INSERTED.* 
WHERE [flag] IS NULL; 
Questions connexes