下面這段SQL腳本,可以根據單個數據庫中所有文件(數據文件、日志文件等)的大小,來收縮數據庫文件:
DECLARE @databaseFiles TABLE ( freeSpace FLOAT, fileName NVARCHAR(300) ) INSERT INTO @databaseFiles(freeSpace,fileName) SELECT CAST(size AS FLOAT) / FILEPROPERTY(name, 'SpaceUsed') AS freeSpace,--sys.database_files的size列是數據庫文件目前的大小(返回的是數據庫文件的頁數,每一頁為8KB大小),其中包含分配了但沒有使用的空間大小,FILEPROPERTY(name, 'SpaceUsed')是數據庫文件實際使用的大小(返回的是數據庫文件的頁數,每一頁為8KB大小),所以size一定是大於等於FILEPROPERTY(name, 'SpaceUsed')的,而這里計算出的freeSpace代表了數據庫文件目前的大小是實際使用空間的多少倍 name FROM sys.database_files AS df WHERE df.type_desc = N'ROWS'--這里,如果要收縮數據庫的數據文件(mdf,ndf)就是ROWS,如果要收縮數據庫的日志文件(ldf)就是LOG WHILE (SELECT COUNT(1) FROM @databaseFiles)>0 BEGIN DECLARE @FreeSpace FLOAT ,@FileName NVARCHAR(300) ,@NewSize INT SELECT TOP 1 @FileName=fileName,@FreeSpace=freeSpace FROM @databaseFiles IF @FreeSpace > 2.5--如果數據庫文件目前的大小超過了實際使用空間的2.5倍,就收縮該數據庫文件 BEGIN SELECT @NewSize = CEILING(FILEPROPERTY(name, 'SpaceUsed') / 128 * 1.1)--將數據庫文件收縮到實際使用空間的1.1倍 FROM sys.database_files AS df WHERE df.type_desc = N'ROWS'--這里,如果要收縮數據庫的數據文件(mdf,ndf)就是ROWS,如果要收縮數據庫的日志文件(ldf)就是LOG DBCC SHRINKFILE (@FileName, @NewSize) END DELETE FROM @databaseFiles WHERE fileName=@FileName END
注意,其中用到的一些SQL Server系統視圖和函數,可以查看下面這幾個微軟官方文檔:
sys.database_files (Transact-SQL)
DBCC SHRINKFILE (Transact-SQL)