Necesito soltar y volver a crear una tabla, que existe para "almacenar en caché" una vista costosa. La vista puede cambiar y quiero que el mantenimiento sea lo más fácil posible, por lo que quiero que la nueva tabla refleje la última versión de la vista.Servidor SQL - Suelta y recrea una tabla - Bloquea el acceso mientras lo haces
También quiero ser capaz de evitar errores de lectura si un procedimiento intenta acceder a la tabla mientras está en el medio de ser descartada y recreada. Estoy usando una transacción, pero no estoy seguro de si eso funcionará en una tabla "descartada" por esa fracción de segundo que no existe.
Hice una prueba básica, 30 x SELECT de la vista en un bucle mientras ejecutaba la vista desplegable/recrear. Sin errores hasta ahora.
He considerado un Truncar/Eliminar con inserción, pero las columnas potencialmente cambiantes en la vista en el futuro requieren que lo mantenga lo más flexible posible, y las columnas fijas no me ayudarán con esto.
¿Alguien me puede decir si la transacción protegerá la mesa del acceso de lectura mientras se retira y esto es seguro, o si hay una forma mejor?
gota/Código Recrear:
BEGIN TRAN
BEGIN TRY
DROP TABLE Persisted_View_1
SELECT * INTO Persisted_View_1
FROM View_1
END TRY
BEGIN CATCH
RAISERROR('The procedure proc_PersistView1 failed to commit, the transaction was rolled back', 16, 1)
IF @@TRANCOUNT > 0
BEGIN
ROLLBACK TRAN
END
END CATCH
IF @@TRANCOUNT > 0
BEGIN
COMMIT TRAN
END
GO
ACTUALIZACIÓN: consulta revisado siguientes clavitos Respuesta:
ALTER PROCEDURE proc_Drop_Recreate_Persisted_View_MyData
AS
BEGIN
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN
BEGIN TRY
-- Re create
SELECT * INTO Persisted_View_MyData_Temp FROM View_MyData
-- Create index on product ID
CREATE CLUSTERED INDEX [IX_ProductID_ProductTypeID] ON [dbo].[Persisted_View_MyData_Temp]
(
[productID] ASC,
[productTypeID] ASC
)
WITH
(PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
-- Check and drop table
IF EXISTS (SELECT Id FROM sysObjects WHERE Name like 'Persisted_View_MyData')
BEGIN
DROP TABLE Persisted_View_MyData
END
EXEC sp_rename 'Persisted_View_MyData_Temp', 'Persisted_View_MyData'
END TRY
BEGIN CATCH
RAISERROR('The procedure proc_PersistViewMyData failed to commit, the transaction was rolled back', 16, 1)
IF @@TRANCOUNT > 0
BEGIN
ROLLBACK TRAN
END
END CATCH
IF @@TRANCOUNT > 0
BEGIN
COMMIT TRAN
END
END
En lugar de utilizar esta tabla de almacenamiento en caché manual, ¿puede materializar la vista haciéndola una vista indexada? Entonces, SQL debería encargarse de todos estos detalles por usted. (Tenga en cuenta que ciertas construcciones en la vista podrían descartar esto, como UNIONs o GROUP BYs) – BradC
@BradC, ¿puede comentar más sobre cómo hacer que una vista sea una "vista indexada"? – Brad
@Brad Amplió mi comentario en una respuesta. Vea abajo. – BradC