E-Mail:
Get our new Windows 7 eBook (PDF) for $7 with 70+ Tips. Download Now!

Inserting DBCC CHECKDB Results Into A Table

Hello again and welcome back!

I thought today’s posting to my blog should cover how to get the results of DBCC CHECKDB into a table.  Unfortunately, Microsoft does not allow you easily per se to insert the results into a table so that you might be able to generate administrative reports off of.  Well in my case that is exactly why I developed this process… to generate administrative reports off of.

Now what I did as you will see in the T-SQL scripts below, I created a table based upon the result set of the DBCC CHECKDB execution.  Once I had the column names and data types I went ahead and created the table.  The next step was to write a stored procedure that would iterate through all databases on the server, run the DBCC CHECKDB statement and record the output into the table I just created.  So after much testing and a little taste of success I give you the scripts below.  I call the stored procedure in a SQL Server Agent job and schedule the job to run in the early hours of the morning and ’off peak’ hours.  So in the morning I can review the results of DBCC CHECKDB from the previous night.  Now you can modify this process to just append the data or just truncate it like I did.  I hope you find this code helpful!… Let us know!…

Here is the table script (this script is for the SQL Server 2005 CHECKDB output)

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[CheckDBResult](
 [ServerName] [varchar](100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
 [Error] [int] NULL,
 [Level] [int] NULL,
 [State] [int] NULL,
 [MessageText] [varchar](7000) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
 [RepairLevel] [int] NULL,
 [Status] [int] NULL,
 [DbId] [int] NULL,
 [Id] [int] NULL,
 [IndId] [int] NULL,
 [PartitionId] [int] NULL,
 [AllocUnitId] [int] NULL,
 [File] [int] NULL,
 [Page] [int] NULL,
 [Slot] [int] NULL,
 [RefFile] [int] NULL,
 [RefPage] [int] NULL,
 [RefSlot] [int] NULL,
 [Allocation] [int] NULL,
 [insert_date] [datetime] NOT NULL CONSTRAINT [DF_CheckDBResult_insert_date]  DEFAULT (getdate())
) ON [PRIMARY]

GO
SET ANSI_PADDING OFF

Here is the CREATE PROCEDURE script that utilizes the CHECKDB 2005 output and here is the T-SQL syntax to execute the procedure: EXEC mDBMaintenance ‘Lumiere’ <- server name to run the script against

EXEC Admin_GetCheckDBResults ’server name’

set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON

GO
CREATE PROCEDURE [dbo].[Admin_GetCheckDBResults]
 @ServerName VARCHAR(100)
 
AS
DECLARE
@Database SYSNAME
 
– Remove Previous Weeks Results
TRUNCATE TABLE DBA_Admin.dbo.CheckDBResult
 
DECLARE cDatabases CURSOR FOR
SELECT [name] from master..sysdatabases AS sdb
WHERE sdb.[name] NOT IN (‘tempdb’)
OPEN cDatabases
FETCH FROM cdatabases INTO @Database
WHILE ( @@FETCH_STATUS = 0)
BEGIN
 SET NOCOUNT ON

 
 INSERT INTO DBA_Admin.dbo.CheckDBResult(
  Error,
  [Level],
  [State],
  MessageText,
  RepairLevel,
  [Status],
  [DbId],
  Id,
  IndId,
  PartitionId,              — specific to SQL Server 2005, remove for SQL Server 2000 results
  AllocUnitId,             — specific to SQL Server 2005, remove for SQL Server 2000 results
  [File],
  Page,
  Slot,
  RefFile,
  RefPage,
  RefSlot,
  Allocation
  )
 EXEC (‘DBCC CHECKDB(”’ + @Database + ”’) WITH TABLERESULTS’)
 
FETCH FROM cdatabases INTO @Database
END
CLOSE
cDatabases
DEALLOCATE cDatabases
 
– Remove all details except CHECKDB information
DELETE
FROM
DBA_Admin.dbo.CheckDBResult
WHERE MessageText NOT LIKE ‘CHECKDB%’
 
– Update server Name
UPDATE DBA_Admin.dbo.CheckDBResult
SET ServerName = @ServerName
 
– Select Statment To Return Rows
SELECT ServerName,
 MessageText,
 Error,
 [Level],
 [State],
 RepairLevel,
 [Status],
 [DbId],
 Id,
 IndId,
 PartitionId,          – specific to SQL Server 2005, remove for SQL Server 2000 results
 AllocUnitId,         – specific to SQL Server 2005, remove for SQL Server 2000 results
 [File],
 Page,
 Slot,
 RefFile,
 RefPage,
 RefSlot,
 Allocation,
 Insert_Date
FROM DBA_Admin.dbo.CheckDBResult
GO

Now as you can see I only want to see the last line in the DBCC CHECKDB command… however, you can modify it keep all the detail from the execution.  I hope this code helps and let us know how you are using it!

3 Comments

John Zacharkan

June 23rd, 2009
at 8:19am

Nice work SQLSquirrel,

Fantastic to see how others go about monitoring their environments. What I like especially is the flexibility to query the results and make decisions as needed.

Couple of quick observations based on my SQL 2005 EE

Repairlevel is a varchar I’m using (255)
PartionID bigint
AllocUnitId bigint

Without these changes the procedure fails on insert when checkdb comes on a consistency error.

thanks greatly and keep up the great work.

cheers
Zach

Thank you very much, SQLSquirrel! I did use some of your code from above. I have a very large environment (50 instances of SQL2000 and SQL2005) and I am setting up a Master/Target Server Job to execute CHECKDB against all databases in an instance. But, I had a couple special requirements from my manager for this solution, and I ran into something with the first few rounds of testing.

First off, Zach above is correct. I also have SQL 2005 Enterprise and I had a few columns that didn’t match up. Thank you to Zach!

Second, we don’t care about any results if there is nothing wrong with the database, so we are using :
WITH NO_INFOMSGS, TABLERESULTS.
This will only return rows if there is actually something wrong with the database.

This is part of a larger solution for us, as we are also trying to retain some level of history for databases, file sizes, checkdb scans, etc. I have 4 tables in the master database that we are writting to: DatabaseList, DatabaseFileInfo, CheckDBScanList, and CheckDBErrors. Since the DatabaseList table is updated daily, I use this to build my cursor of work, excluding databases that no longer exist (expired rows). I use Database ID number for the CHECKDB command in my code, I find it much easier/cleaner than using the database name. Also, I exclude all four system databases. I am also tracking the scan in the CheckDBScanList table. This table gets a row with the start time just before calling the CHECKDB command, and writes stop time and a zero or one based on the results of the scan (if there is something in the #temp table from the scan, the scan “failed” and rows are written to CheckDBErrors, otherwise, the scan succeeded). Of course, after each scan, I truncate the #temp, just in case. :D

If you want more information, feel free to message me. Thanks!

James Kerr

Thanks to all of you for your thoughts and contributions… yes, yes as well as your corrections! :0) I know I appreciate it as well other SQL Server professionals that read this blog post.

All of you help to keep this blog going with your excellent feedback and insightful tips!

What Do You Think?

 

Posted Recently

40 queries / 0.246 seconds.