简体   繁体   中英

DBCC SHRINKFILE 1 sproc for multiple databases

I have a need to execute DBCC SHRINKFILE for multiple db'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
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

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! .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM