SQL: DBCC CHECKTABLE on multiple tables
Part of decent SQL database maintenence is periodically checking the integrity, both logical and physical, of database objects. SQL Server has the DBCC CHECKDB command that will check the integrity of the objects and report back the results. DBCC CHECKDB runs CHECKALLOC, CHECKTABLE and CHECKCATALOG on the specified database.

DBCC CHECKTABLE allows you to check the integrity of a specified table or indexed view. If there are a large number of tables to check, the task of running the command for each tablename could be time consuming. Creating a script that loops through a set of database tables and runs DBCC CHECKTABLE for each, is a bit easier.
The sys.objects contains each of the user-defined schema objects in a database. Rows that are of [Type] = 'U' are tables. This makes it easy to get all the tables within a database (of course other filters can be applied). The following script will loop through and run the DBCC CHECKTABLE command for each table in the database (the command can be easily replaced to perform another action on each returned table):
-- set options
SET NOCOUNT ON;
SET ANSI_PADDING ON;
SET ANSI_NULLS ON;
SET QUOTED_IDENTIFIER ON;
-- declare table to store table names
-- in SQL 2005 you can use table variables
-- if you do not need or want to store the data you can store it in a table
-- variable instead of a temporary table
DECLARE @tablenames TABLE (
TableName VARCHAR(255)
);
-- populate table with tablenames
INSERT INTO @tablenames
SELECT
name
FROM
sys.objects
-- additional filters can be set to narrow table selection
WHERE
([type] = N'U');
-- Declare a cursor to loop through table
DECLARE tablenames INSENSITIVE SCROLL CURSOR
FOR
SELECT
TableName
FROM
@tablenames;
-- Open the cursor.
OPEN tablenames
-- declare variables
DECLARE @curtablename AS VARCHAR(255);
DECLARE @cmd AS VARCHAR(1024);
-- Loop through all the tables
WHILE (1=1)
BEGIN
FETCH NEXT FROM tablenames INTO @curtablename;
IF @@fetch_status <> 0 BREAK;
-- run the command
SET @cmd = 'DBCC CHECKTABLE ([' + rtrim(@curtablename) + '])';
EXEC (@cmd)
PRINT @cmd + CHAR(10) + CHAR(13);
END
-- Close cursor
CLOSE tablenames;
DEALLOCATE tablenames;
SQL: Index Fragmentation Maintenance
In a previous post, I discussed SQL Server's built in ability for suggesting missing indexes. As records are inserted, updated and deleted from tables indexes can become fragmented.
A fragmented index affects performance (table scans and index seeks) when the DBMS needs to search for records.
This probably leaves the question, "How can one defragment the indexes of SQL tables?"
Within SQL Server 2005 and greater you can setup a maintenance plan to defragment all the indexes within all or a particular database. You can also right click on an index and select to either Rebuild or Reorganize and index (rebuilding will re-create the index whereas reorganize reorders the index pages).
I prefer to have a little more control and use the following script as part of my maintenance plan. This script allows for a little more control in the selecting of tables, indexes and databases to maintain. I tend to rebuild indexes that are more than 30% fragmented and reorganize those that are greater than 5%.
SQL Server 2005 (and greater) has index information more readily accessible. The key to this script is the index information that is contained in sys.dm_db_index_physical_stats. This table returns the size and fragmentation information for each index.
-- ########################################
-- Create table to hold index information
SET NOCOUNT ON;
CREATE TABLE _IndexInformation (
database_id SMALLINT
,ObjectName varchar(255)
,[object_id] int
,IndexName varchar(255)
,[index_id] int
,index_level int
,index_type_desc varchar(60)
,avg_fragmentation_in_percent float
,fragment_count float
,page_count bigint
,record_count bigint
,index_depth int
);
-- ########################################
-- ########################################
-- clear table contents
TRUNCATE TABLE _IndexInformation;
-- populate table
INSERT INTO _IndexInformation
SELECT
database_id
,object_name(i.object_id) AS [ObjectName]
,i.[object_id]
,i.name AS [IndexName]
,dm.index_id
,dm.index_level
,dm.index_type_desc
,dm.avg_fragmentation_in_percent
,dm.fragment_count
,dm.page_count
,dm.record_count
,dm.index_depth
FROM
-- database, table and index information can be specified
/*
sys.dm_db_index_physical_stats (
{ database_id NULL 0 DEFAULT }
,{ object_id NULL 0 DEFAULT }
,{ index_id NULL 0 -1 DEFAULT }
,{ partition_number NULL 0 DEFAULT }
,{ mode NULL DEFAULT }
)
This example uses database 1; you should replace this with the ID of the database you wish to process
*/
sys.dm_db_index_physical_stats(1,null,null,null,'detailed') dm INNER JOIN sys.indexes i
ON (i.object_id = dm.object_id) AND (i.index_id = dm.index_id);
-- ########################################
-- ########################################
-- read index table and maintain indexes
SET NOCOUNT ON;
SET ANSI_PADDING ON;
SET ANSI_NULLS ON;
SET QUOTED_IDENTIFIER ON;
-- Declare variables.
DECLARE @tablename AS varchar(255)
DECLARE @indexname AS varchar(255)
DECLARE @frag AS float
DECLARE @cmd AS varchar(1024)
-- Declare a cursor.
DECLARE indexes INSENSITIVE SCROLL CURSOR
FOR
SELECT
ObjectName,
IndexName,
avg_fragmentation_in_percent
FROM
_IndexInformation
WHERE
(avg_fragmentation_in_percent >= 5);
-- Open the cursor.
OPEN indexes
-- Loop through all the indexes.
WHILE (1=1)
BEGIN
FETCH NEXT FROM indexes INTO @tablename, @indexname, @frag;
IF @@fetch_status <> 0 BREAK;
-- if fragmentation is above 30% rebuild index
-- if fragmentation is above 5% reorganize index
IF (@frag >= 30)
BEGIN
SET @cmd = 'ALTER INDEX [' + rtrim(@indexname) + '] ON [' + @tablename +'] REBUILD;'
EXEC (@cmd)
PRINT @cmd;
END
ELSE IF (@frag >= 5)
BEGIN
SET @cmd = 'ALTER INDEX [' + rtrim(@indexname) + '] ON [' + @tablename +'] REORGANIZE;'
EXEC (@cmd)
PRINT @cmd;
END;
END
-- Close cursor
CLOSE indexes;
DEALLOCATE indexes;
-- ########################################
-- ########################################
-- delete index table
DROP TABLE _IndexInformation;
-- ########################################

I have the script schedule to as part of my database maintenance plan. I run the script several times with additional selection criteria limiting it to groups of tables in a particular database.
Off-topic: Uhm, Rickroll?
Last weekend I did a search for a video on YouTube. When the search results came up I clicked the link to a video that seemed to be the most relevant. The video queued up and the video for Rick Astley's "Never Gonna Give You Up" song started to play. Over the video the words 'You have just been Rickrolled' appeared. It took me a moment, but then I realized something funny was going on. I did a quick Google search for 'Rickrolled' and found out exactly what it was...
The weird thing is that I had never heard any hype or talk about
'Rickrolling' until last weekend. Over the past week, I have heard mention of
Rickrolling in some form of media.
'Rickrolling' appeared in blogs, news articles and I even heard radio hosts discussing it.
The whole thing is sort of comical to me. Was it that I had never paid attention or is it that the
RickRolling buzz is still new?
How long will it last?
Now that gives me an idea.......