在While循环中如何执行"使用[数据库名称] Go"

时间:2013-07-31 20:31:08

标签: sql-server tsql while-loop

我需要每周缩小每个数据库的日志文件。 我正在编写一个while循环查询来循环每个数据库。但我认为不允许这样做:

declare @database_id int
declare @database varchar(255)
declare @log varchar(255)
declare @cmd varchar(500)

while (select count(*) from #LogFiles where processed = 0) > 0
begin 

    set @database_id = (select min(database_id) from #LogFiles where processed = 0)
    set @database = (select name from #LogFiles where database_id = @database_id and [type] = 0)
    set @log = (select name from #LogFiles where database_id = @database_id and [type] = 1)

    select @database, @log

        set @cmd = 'Use ' + @Database
        exec(@cmd)

    set @cmd = 'DBCC SHRINKFILE (' + @log + ');'

    exec(@cmd)

    update #LogFiles 
    set processed = 1
    where database_id = @database_id

end

还是有另一种方法吗?

由于

1 个答案:

答案 0 :(得分:5)

正如多篇评论中所提到的,这真的,真的,真的不是一个好主意。收缩这些文件只是为了让他们下周再次成长是浪费精力,因为日志文件自动增长事件无法利用即时文件初始化(因为,与数据文件分配不同,日志文件分配在使用前必须归零) ,这可能会以您无法预测或控制的方式影响最终用户的表现。

也就是说,在循环时抛弃#temp表和游标。从技术上讲,这仍然使用循环来连接,但设置和查看起来要容易得多。

DECLARE @sql NVARCHAR(MAX); SET @sql = N'';

SELECT @sql = @sql + N'
  USE ' + QUOTENAME(db) + ';
  PRINT DB_NAME();
  CHECKPOINT; -- since we now know it is simple recovery
  DBCC SHRINKFILE(' + QUOTENAME(f) + ') WITH NO_INFOMSGS;'
FROM
(
  SELECT DB_NAME(database_id), name
   FROM sys.master_files
   WHERE database_id > 4 AND [type] = 1
   -- AND LOWER(name) NOT IN (N'reportserver', N'reportservertempdb')
) AS x(db, f);

PRINT @sql;
--EXEC sp_executesql @sql;

查看PRINT输出。如果您满意,它会按照您的想法执行操作,取消注释EXEC并再次运行。