2012-03-23 38 views
5

Tengo una gran tabla que se llena desde una vista. Esto se hace porque la vista tarda mucho tiempo en ejecutarse y es más fácil tener los datos disponibles en una tabla. Se ejecuta un procedimiento de vez en cuando que actualiza la tabla.Bloquear tabla al insertar

TRUNCATE TABLE LargeTable 

INSERT INTO LargeTable 
SELECT * 
FROM viewLargeView 
WITH (HOLDLOCK) 

me gustaría para bloquear esta tabla al insertar por lo que si alguien trata de seleccionar un registro que no recibirán ninguno después del truncado. El bloqueo que estoy usando parece bloquear la vista y no la tabla.

¿Hay una mejor manera de abordar este problema?

+1

¿Qué hay de abrir una transacción antes de la inserción y cerrarla después? –

+0

Al abrir una transacción, ¿puede otro usuario seleccionarla de la tabla? – JBone

+0

FYI, le recomendaría que utilice DELETE en lugar de TRUNCATE, ya que TRUNCATE es un DDL, en lugar de un DML como DELETE, y por lo tanto requiere mayores permisos. Además, si envuelve esto en una transacción (que es la respuesta correcta a su pregunta), efectivamente realizará el mismo. – RBarryYoung

Respuesta

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

No crea que esto podría hacer nada. El 'truncado' no se ve afectado por una transacción, y un inserto por sí mismo también es una transacción, incluso si no especifica uno. – Andomar

+0

En realidad, TRUNCATE se revierte con algunas advertencias. Ver [esto] (http://blog.sqlauthor.es/2007/12/26/sql-server-truncate-cant-be-rolled-back-using-log-files-after-transaction-session-is-closed /) –

4

Es cierto que su pista de bloqueo correcta afecta a la vista de origen.

Para hacerlo de modo que nadie pueda leer de la mesa mientras se está insertando:

insert into LargeTable with (tablockx) 
... 

Usted no tiene que hacer nada para que la tabla de consulta vacía hasta después de la inserción completa. Una inserción siempre se ejecuta en una transacción, y ningún otro proceso puede leer las filas no confirmadas, a menos que especifiquen explícitamente with (nolock) o set transaction isolation level read uncommitted. No hay forma de protegerme de eso hasta donde yo sé.

Cuestiones relacionadas