How to find which columns don't have any data (all values are NULL)?
For a single column, count(ColumnName)
returns the number of rows where ColumName
is not null:
select count(TheColumn)
from YourTable
You can generate a query for all columns. Per Martin's suggestion, you can exclude columns that cannot be null with is_nullable = 1
. For example:
select 'count(' + name + ') as ' + name + ', '
from sys.columns
where object_id = object_id('YourTable')
and is_nullable = 1
If the number of tables is large, you can generate a query for all tables in a similiar way. The list of all tables is in sys.tables
.
Here's a script I wrote to do the same thing, it's a two-step manual process:
- Run this script in SSMS and select all of the rows in the Results pane:
SELECT 'SELECT COUNT( DISTINCT [' + COLUMN_NAME + ']) AS UniqueValues, ''' + TABLE_NAME + '.' + COLUMN_NAME + ''' AS ColumnName FROM [' + TABLE_SCHEMA + '].[' + TABLE_NAME + '] UNION ALL ' FROM INFORMATION_SCHEMA.COLUMNS ORDER BY TABLE_NAME, COLUMN_NAME
- Paste the results into a new query window. Scroll to the very bottom and remove the trailing
UNION ALL
statement. It will look like this:
SELECT COUNT( DISTINCT [ModifiedByUserId]) AS UniqueValues, 'Inspections.ModifiedByUserId' AS ColumnName FROM [dbo].[Inspections] UNION ALL SELECT COUNT( DISTINCT [Notes]) AS UniqueValues, 'Inspections.Notes' AS ColumnName FROM [dbo].[Inspections] UNION ALL SELECT COUNT( DISTINCT [PublicPassword]) AS UniqueValues, 'Inspections.PublicPassword' AS ColumnName FROM [dbo].[Inspections] UNION ALL SELECT COUNT( DISTINCT [ShopId]) AS UniqueValues, 'Inspections.ShopId' AS ColumnName FROM [dbo].[Inspections] UNION ALL SELECT COUNT( DISTINCT [Status]) AS UniqueValues, 'Inspections.Status' AS ColumnName FROM [dbo].[Inspections] UNION ALL SELECT COUNT( DISTINCT [SupervisorUserId]) AS UniqueValues, 'Inspections.SupervisorUserId' AS ColumnName FROM [dbo].[Inspections] UNION ALL
- Run the query. It took about 6 minutes to run on a 300-column database. It will be faster or slow depending on how many indexes are being used.
Updated....Okay I had way too much fun with this
THe Proc accepts two parameters, the table to search & the Criteria to apply. you can pass essentially and where clause to the second parameter. I wrote the proc to interpret double quotes back to single quotes....again this was built off of the original developers concepts.
GO
/****** Object: StoredProcedure [dbo].[SearchAllTables] Script Date: 05/04/2011 14:29:48 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
alter PROC [dbo].[SearchAllTables2] ( @SEARCH_TABLE NVARCHAR(255), @CONDITION AS NVARCHAR(MAX) ) AS
BEGIN
-- Copyright © 2002 Narayana Vyas Kondreddi. All rights reserved.
-- Purpose: To search all columns of all tables for a given search string
-- Written by: Narayana Vyas Kondreddi -- Site: http://vyaskn.tripod.com
-- Tested on: SQL Server 7.0 and SQL Server 2000
-- Date modified: 28th July 2002 22:50 GMT
CREATE TABLE #Results (ColumnName nvarchar(370), ColumnValue nvarchar(3630))
SET NOCOUNT ON
DECLARE @TableName nvarchar(256), @ColumnName nvarchar(128), @SearchStr2 nvarchar(110), @COND_STR NVARCHAR(MAX)
SET @TableName = ''
--SET @SearchStr2 = QUOTENAME('%' + @SearchStr + '%','''')
WHILE @TableName IS NOT NULL
BEGIN
SET @ColumnName = ''
SET @CONDITION = REPLACE(@CONDITION,'"','''')
SET @TableName =
(
SELECT MIN(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME))
FROM INFORMATION_SCHEMA.TABLES
WHERE
TABLE_TYPE = 'BASE TABLE'
AND
QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) > @TableName
AND OBJECTPROPERTY(
OBJECT_ID(
QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)
), 'IsMSShipped'
) = 0 AND TABLE_NAME = @SEARCH_TABLE
) WHILE (@TableName IS NOT NULL) AND (@ColumnName IS NOT NULL)
BEGIN SET @ColumnName = (
SELECT MIN(QUOTENAME(COLUMN_NAME))
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = PARSENAME(@TableName, 2) AND
TABLE_NAME = PARSENAME(@TableName, 1) AND QUOTENAME(COLUMN_NAME) > @ColumnName )
IF @ColumnName IS NOT NULL
BEGIN
SET @COND_STR = REPLACE(@CONDITION,'''','"')
INSERT INTO #Results
EXEC ( 'SELECT DISTINCT ''' + @TableName + '.' + @ColumnName + ''',''' + @COND_STR + ''' AS CONDITION FROM ' + @TableName + ' (NOLOCK) ' + ' WHERE ' + @ColumnName + ' ' + @CONDITION)
PRINT ( 'SELECT DISTINCT ''' + @TableName + '.' + @ColumnName + ''',''' + @COND_STR + ''' AS CONDITION FROM ' + @TableName + ' (NOLOCK) ' + ' WHERE ' + @ColumnName + ' ' + @CONDITION)
END
END
END
SELECT ColumnName, ColumnValue
FROM #Results
END
GO
-- to execute
exec [SearchAllTables2] 'TABLENAME','LIKE "%DOUG%"' -- double quotes are automatically escaped to single quotes...
Original code modified from copyright below....only using portions.
GO
/****** Object: StoredProcedure [dbo].[SearchAllTables] Script Date: 05/04/2011 14:29:48 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
alter PROC [dbo].[SearchAllTables2] ( @TABLE_NAME NVARCHAR(255) ) AS
BEGIN
-- Copyright © 2002 Narayana Vyas Kondreddi. All rights reserved.
-- Purpose: To search all columns of all tables for a given search string
-- Written by: Narayana Vyas Kondreddi -- Site: http://vyaskn.tripod.com
-- Tested on: SQL Server 7.0 and SQL Server 2000
-- Date modified: 28th July 2002 22:50 GMT
CREATE TABLE #Results (ColumnName nvarchar(370), ColumnValue nvarchar(3630))
SET NOCOUNT ON
DECLARE @TableName nvarchar(256), @ColumnName nvarchar(128), @SearchStr2 nvarchar(110)
SET @TableName = ''
--SET @SearchStr2 = QUOTENAME('%' + @SearchStr + '%','''')
WHILE @TableName IS NOT NULL
BEGIN
SET @ColumnName = ''
SET @TableName =
(
SELECT MIN(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME))
FROM INFORMATION_SCHEMA.TABLES
WHERE
TABLE_TYPE = 'BASE TABLE'
AND
QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) > @TableName
AND OBJECTPROPERTY(
OBJECT_ID(
QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)
), 'IsMSShipped'
) = 0 AND TABLE_NAME = @TABLE_NAME
) WHILE (@TableName IS NOT NULL) AND (@ColumnName IS NOT NULL)
BEGIN SET @ColumnName = (
SELECT MIN(QUOTENAME(COLUMN_NAME))
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = PARSENAME(@TableName, 2) AND
TABLE_NAME = PARSENAME(@TableName, 1) AND QUOTENAME(COLUMN_NAME) > @ColumnName )
IF @ColumnName IS NOT NULL
BEGIN
INSERT INTO #Results
EXEC ( 'SELECT DISTINCT ''' + @TableName + '.' + @ColumnName + ''', ''IS NULL'' FROM ' + @TableName + ' (NOLOCK) ' + ' WHERE ' + @ColumnName + ' IS NULL ')--LIKE ' + @SearchStr2 )
--PRINT ( 'SELECT DISTINCT ''' + @TableName + '.' + @ColumnName + ''', ''IS NOT NULL'' FROM ' + @TableName + ' (NOLOCK) ' + ' WHERE ' + @ColumnName + ' IS NOT NULL ')--LIKE ' + @SearchStr2 )
END
END
END
SELECT ColumnName, ColumnValue
FROM #Results
END
GO
-- to execute
exec [SearchAllTables2] 'Master'