Si has llegado a este artículo, lo más probable es que estés intentando reducir un fichero de base de datos de SQL Server en varios gigas y el proceso se haya eternizado.

El caso práctico para el que he tenido que hacer el siguiente script: Una base de datos de 400GB con el 50% del espacio libre.

Intentar un shrink de 200GB podría haber durado varias horas. En algunos foros habrás encontrado que es más efectivo reducir en tramos de 500MB o 1GB, y eso es lo que conseguiras con este script:

-- Shrink por etapas
DECLARE @mb_comienzo INT
DECLARE @mb_limite INT

SET @mb_comienzo = 440000 --Tamaño actual del fichero en MB
SET @mb_limite = 210000 -- Tamaño deseado en MB

USE []

WHILE (@mb_comienzo>@mb_limite)
BEGIN
    SET @mb_comienzo = @mb_comienzo - 500
    PRINT 'Reduciendo a: ' + CAST(@mb_comienzo AS VARCHAR) + 'MB.'
    DBCC SHRINKFILE (N'' , @mb_comienzo)
END


Se le puede añadir más complejidad. Pero es más que suficiente para salir del paso y empezar a obtener espacio libre en una situación de emergencia.

Por ejemplo, podríamos consultar qué datafiles son candidatos a ser reducidos con este procedimiento, porque tienen más de 10GB libres:

-- Ficheros candidatos a hacer el shrink por etapas (con más de 10GB para reducir)
DECLARE @sql VARCHAR(8000)
DECLARE @script VARCHAR(MAX)

SET @sql='SELECT DB_NAME() AS BD,
name AS FileName,
CONVERT(INT,size/128.0) AS MBactual,
CONVERT(INT,size/128.0 - CAST(FILEPROPERTY(name, ''SpaceUsed'') AS INT)/128.0) AS MBlibre
FROM sys.database_files
WHERE (size/128.0 - CAST(FILEPROPERTY(name, ''SpaceUsed'') AS INT)/128.0)>10000'
SET @script=''

SELECT @script = @script + 'USE ' + name + CHAR(13) + @sql + CHAR(13) + CHAR(13)
FROM sys.databases

--PRINT(@script)
EXECUTE(@script)