DBCC SHRINKFILE 1 sproc for multiple databases
I have a need to execute DBCC SHRINKFILE for multiple db'开发者_JS百科s within the same sproc. I could create multiple sprocs so it runs within the given context, but I was curious if there were alternatives?
Here is the code I use to perform this operation to shrink the logs on the databases beginning with 'MPS_' that are simple recovery. This can be set as an SQL Execution Task maintenance plan and scheduled as appropriate. The current code shrinks the log to 1 GB, which for us does a decent job of avoiding disk fragmentation.
Note that these are all volatile databases. Never do this to production databases unless you really know what you're doing. Also, do not just do this to every simple recovery model database. Several of the system databases (master
, for one) are simple recovery!
use [master]
set nocount on
declare @name sysname,
@file_id int,
@sqlcmd varchar(max)
DECLARE db_mps_simple_logs_cur CURSOR FOR
select d.name, mf.file_id
from sys.databases d
join sys.master_files mf
on d.database_id = mf.database_id
where d.[name] like 'MPS_%'
and d.recovery_model = 3 --simple only
and mf.type = 1 --0 is data, 1 is log
open db_mps_simple_logs_cur
fetch next from db_mps_simple_logs_cur into @name, @file_id
while @@fetch_status = 0 begin
set @sqlcmd = 'use ' + QUOTENAME(@name) + '; checkpoint; dbcc shrinkfile ( ' + cast(@file_id as varchar) + ', 1024 );'
exec ( @sqlcmd )
fetch next from db_mps_simple_logs_cur into @name, @file_id
end
close db_mps_simple_logs_cur
deallocate db_mps_simple_logs_cur
go
Here is a nice command that will show the current transaction log sized for simple recovery model databases so you can easily see the resuts:
select
d.database_id,
d.name,
d.recovery_model_desc,
mf.name [file_name],
mf.size * 8 / 1024 [size_in_mb],
d.log_reuse_wait_desc
from sys.databases d
join sys.master_files mf
on d.database_id = mf.database_id
where d.[name] like 'MPS_%'
and d.recovery_model = 3 --simple only
and mf.type = 1 --0 is data, 1 is log
order by mf.size desc
Your best approach is, by far, to never write a script that shrinks a database file. From the million destructive things you can do with a database, shrinking it is right there in top 3. See Auto-shrink – turn it OFF!.
EXEC sp_MSForEachDB 'USE ? DBCC SHRINKFILE (fileid, targetsize)'
The undocumented sp_MSForEachDB is your friend here
Edit, after Raj's comment
EXEC sp_MSForEachDB '
USE ?
IF DB_NAME() IN (''DB1'', ''DB1'', ''DB1'')
DBCC SHRINKFILE (fileid, targetsize)
'
Edit
Note to downvoters, the dynamic SQL in the highest voted answer is basically a cut down sp_MSForEachDB
精彩评论