Skip to content
SQL-Mac

Check for Corruption Across Multiple Databases

16th July 2017
DBA & SQL
tsql
sql server
dbcc
maintenance
Last updated:18th April 2026
3 Minutes

Check Multiple Databases Quickly

If you work in a shop with many SQL Servers, you’ve either already dealt with a storage issue or you will. Storage controllers going down, unexpected shutdowns, someone hitting the power button on a database server — all of these are good ways to end up with corruption. That’s why weekly DBCC checks are non-negotiable, but sometimes you need to run ad-hoc checks across a lot of databases quickly.

I ran into this situation after a storage controller failure knocked down several SQL instances. The task: check a large number of smaller databases for corruption quickly without blocking everything else for hours. The approach we settled on:

  • Physical-only checks with DBCC CHECKDB (faster, still catches page corruption)
  • Only target databases under 1GB (larger ones could be queued separately)
  • Dynamic SQL so it could run across multiple servers via a management tool

Here’s the script:

-- store database names under 1GB (data files only)
DECLARE @dbcc_physical TABLE (
name NVARCHAR(128) NOT NULL
);
INSERT INTO @dbcc_physical
SELECT d.name
FROM sys.databases d
INNER JOIN sys.master_files f ON d.database_id = f.database_id AND f.type = 0
WHERE d.name NOT IN ('master', 'model', 'msdb', 'tempdb')
GROUP BY d.name
HAVING SUM(f.size) < 131072; -- 131072 pages * 8KB = 1GB
-- cursor to run DBCC CHECKDB on each database
DECLARE @tableCursor CURSOR;
15 collapsed lines
DECLARE @databaseName NVARCHAR(128);
SET @tableCursor = CURSOR FOR SELECT name FROM @dbcc_physical;
OPEN @tableCursor;
FETCH NEXT FROM @tableCursor INTO @databaseName;
WHILE (@@FETCH_STATUS = 0)
BEGIN
EXECUTE ('DBCC CHECKDB(' + QUOTENAME(@databaseName) + ') WITH PHYSICAL_ONLY;');
FETCH NEXT FROM @tableCursor INTO @databaseName;
END;
CLOSE @tableCursor;
DEALLOCATE @tableCursor;

A few notes on the implementation:

  • sys.master_files stores size in 8KB pages, so 131072 pages = 1GB. The original version used size < 1024 which filtered to databases under ~8MB — far too small.
  • sys.databases gives you the database name; sys.master_files gives you the file sizes. You need to join them — querying name directly from sys.master_files returns the logical file name, not the database name.
  • QUOTENAME() wraps the database name to handle spaces or special characters safely.
  • PHYSICAL_ONLY skips logical consistency checks and focuses on structural integrity — significantly faster, appropriate for routine or recovery triage checks.

Adjust the size threshold and the system database exclusion list to fit your environment.

Key Takeaways

  • sys.master_files.size is in 8KB pages — multiply by 8192 to get bytes, or compare to 131072 for a 1GB threshold.
  • Use sys.databases for database names, not sys.master_files.name (which is the logical file name).
  • DBCC CHECKDB WITH PHYSICAL_ONLY is significantly faster and appropriate for triage or high-volume checks.
  • QUOTENAME() is non-optional when building dynamic SQL with database names.

This article, Check for Corruption Across Multiple Databases, was written by sqlmac and first published on 16th July 2017. Original link: https://sqlmac.com/blog/corruption.