2012-03-23 2 views
5

J'ai une grande table remplie à partir d'une vue. Ceci est fait parce que la vue prend beaucoup de temps à s'exécuter et qu'il est plus facile d'avoir les données facilement disponibles dans une table. Une procédure est exécutée de temps en temps pour mettre à jour la table.Verrouiller la table lors de l'insertion

TRUNCATE TABLE LargeTable 

INSERT INTO LargeTable 
SELECT * 
FROM viewLargeView 
WITH (HOLDLOCK) 

Je voudrais verrouiller ce tableau lors de l'insertion donc si quelqu'un essaie de sélectionner un enregistrement, ils ne recevront pas rien après la troncature. Le verrou que j'utilise semble bloquer la vue et non la table.

Existe-t-il une meilleure façon d'aborder ce problème?

+1

Qu'en est-il de l'ouverture d'une transaction avant l'insertion et de la fermeture après? –

+0

Lors de l'ouverture d'une transaction, un autre utilisateur peut-il effectuer une sélection dans la table? – JBone

+0

FYI, je vous recommande d'utiliser DELETE au lieu de TRUNCATE, comme TRUNCATE est un DDL, au lieu d'un DML comme DELETE, et nécessite donc de plus grandes autorisations. De plus, si vous encapsulez ceci dans une Transaction (qui est la réponse correcte à votre question), ils effectueront effectivement la même chose. – RBarryYoung

Répondre

4
BEGIN TRANSACTION t_Transaction 

BEGIN TRY 

TRUNCATE TABLE LargeTable 

INSERT INTO LargeTable 
SELECT * 
FROM viewLargeView 
    WITH (HOLDLOCK) 


COMMIT t_Transaction 

END TRY 

BEGIN CATCH 
    ROLLBACK t_Transaction 
END CATCH 
+0

Ne pensez pas que cela ferait quoi que ce soit. Le 'truncate' n'est pas affecté par une transaction, et un insert tout seul est aussi une transaction, même si vous n'en spécifiez pas. – Andomar

+0

En réalité, les TRUNCATE sont annulées avec quelques mises en garde. Voir [ceci] (http://blog.sqlauthority.com/2007/12/26/sql-server-truncate-cant-be-rolled-back-using-log-files-after-transaction-session-is-closed /) –

4

Il est vrai que votre indication de verrouillage correcte affecte la vue source.

Pour faire en sorte que personne ne puisse lire de la table pendant que vous insérez:

insert into LargeTable with (tablockx) 
... 

Vous ne devez rien faire pour faire regarder la table vide jusqu'à ce que après l'insertion complète. Une insertion s'exécute toujours dans une transaction et aucun autre processus ne peut lire les lignes non validées, sauf si elles spécifient explicitement with (nolock) ou set transaction isolation level read uncommitted. Il n'y a aucun moyen de protéger de cela autant que je sache.

Questions connexes