Claiming back SQL Log space

2012, Nov 20    

I recently had the problem where one of our staging database servers had run out of disk space It contained about 40 databases, each of which was set to Full Recovery mode.

The maintenance jobs had been turned off which meant the log files of each of the databases had grown (the average was a 6gb log) I needed a way to claim back this disk space and without too much effort, and with no regard to what was in the logs. Here’s what i came up with.

It iterates through all databases on an instance of SQL,

CREATE TABLE #tmpDatabases
(
   RowID int IDENTITY(1, 1), 
   [dbId] int,
   dbName VARCHAR(255), 
   recoveryModel int,
   ldfName varchar(255), 
   oldLdfSize int, 
   newLdfSize int,
   mdfName varchar(255), 
   mdfSize int
)

INSERT INTO #tmpDatabases 
select d.database_id, d.name, d.recovery_model, ldf.name [LdfName], ldf.size [LdfSize], 0, mdf.name [MdfName], mdf.size [MdfSize]
from sys.databases d
inner join sys.sysaltfiles ldf on d.database_id = ldf.dbid and ldf.filename like '%ldf'
inner join sys.sysaltfiles mdf on d.database_id = mdf.dbid and mdf.filename like '%mdf'
where d.database_id>4 --only user databases

DECLARE 
@RecoveryModel int,
@DbName varchar(255),
@DbId int,
@LdfName varchar(255),
@SQLUse nvarchar(1024),
@NumberRecords INT,
@RowCount INT

-- Get the number of records in the temporary table
SET @NumberRecords = @@ROWCOUNT
SET @RowCount = 1

WHILE @RowCount  3
	BEGIN
		SET @SQLUse = 'ALTER DATABASE ' + @DbName + ' SET RECOVERY SIMPLE WITH NO_WAIT; '
		EXEC sp_executesql @SQLUse
	END

	--Shrink log file
	SET @SQLUse = 'USE ' + @DbName + '; SELECT DB_NAME() [Current Db]; CHECKPOINT; DBCC SHRINKFILE(' + @LdfName + ', 50); '
	EXEC sp_executesql @SQLUse

	--get new log file size
	update #tmpDatabases
	set newLdfSize = ldf.size
	from #tmpDatabases
	inner join sys.sysaltfiles ldf on #tmpDatabases.[dbid] = ldf.dbid and ldf.filename like '%ldf'
	where #tmpDatabases.[dbId] = @DbId

	--output progress
	select * from #tmpDatabases where #tmpDatabases.[dbId] = @DbId

	SET @RowCount = @RowCount + 1
END

select *, oldLdfSize-newLdfSize [LdfDiff] from #tmpDatabases order by oldLdfSize-newLdfSize desc

drop table #tmpDatabases