I have several tables in a database. I would like to find which columns (in which tables) don't have any values (all NULL in a column). I the example below, the result should be
我在数据库中有几个表。我想找出哪些列(在哪些表中)没有任何值(在一个列中都为空)。我下面的例子,结果应该是
TestTable1 --> Var2
TestTable2 --> Variable1
I don't have any idea how to create this kind of query. Your help is most appreciated!
我不知道如何创建这种查询。非常感谢您的帮助!
--create first table
create table dbo.TestTable1 (
sur_id int identity(1,1) not null primary key,
var1 int null,
var2 int null
)
go
--insert some values
insert into dbo.TestTable1 (var1)
select 1 union all select 2 union all select 3
--create second table
create table dbo.TestTable2 (
sur_id int identity(1,1) not null primary key,
variable1 int null,
variable2 int null
)
--and insert some values
insert into dbo.TestTable2 (variable2)
select 1 union all select 2 union all select 3
4 个解决方案
#1
9
For a single column, count(ColumnName)
returns the number of rows where ColumName
is not null:
对于单个列,count(ColumnName)返回列名称为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:
可以为所有列生成查询。根据Martin的建议,您可以排除is_nullable = 1中不能为空的列。例如:
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
.
如果表的数量很大,您可以以类似的方式为所有表生成查询。所有表的列表都在sys.tables中。
#2
4
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.
Proc接受两个参数:要搜索的表和要应用的标准。您可以将主子句和where子句传递给第二个参数。我写了proc解释双引号回到单引号....这也是基于最初的开发人员概念。
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'
#3
4
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:
- 在SSMS中运行此脚本并选择结果窗格中的所有行:
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: - 将结果粘贴到一个新的查询窗口中。滚动到最底部,并删除后面的UNION ALL语句。它看起来是这样的:
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.
- 运行该查询。在一个300列的数据库上运行大约需要6分钟。这将取决于使用了多少索引,是快还是慢。
#4
2
This is way too useful not to be put into a handy little system proc - especially if you've just inherited a legacy database, and are wondering what columns you can drop or ignore.
这是非常有用的方法,不应该放在一个方便的小系统proc中—特别是如果您刚刚继承了一个遗留数据库,并且想知道可以删除或忽略哪些列。
/*
Show the count of not-null values in a table
*/
create proc sp_aaShowAllNullColumns @tableName varchar(255) as
begin
set nocount on
declare @sql nvarchar(4000)
declare @cols nvarchar(4000)
declare @tcols table( colbit nvarchar(255) )
insert @tcols
select 'count(' + name + ') as ' + name + ', ' as colbit
from sys.columns
where object_id = object_id(@tableName)
and is_nullable = 1
select @cols = coalesce( @cols, ', ', '' ) + colbit from @tcols
select @cols = substring( @cols, 1, (len(@cols) - 1) )
select @cols = isnull( @cols, '' )
select @sql = 'select count(*) as Rows' + @cols + ' from ' + @tableName
exec sp_executeSql @sql
end
go
exec sys.sp_MS_marksystemobject 'sp_aaShowAllNullColumns'
go
use Bookshop
go
exec sp_aaShowAllNullColumns 'Books'
go
#1
9
For a single column, count(ColumnName)
returns the number of rows where ColumName
is not null:
对于单个列,count(ColumnName)返回列名称为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:
可以为所有列生成查询。根据Martin的建议,您可以排除is_nullable = 1中不能为空的列。例如:
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
.
如果表的数量很大,您可以以类似的方式为所有表生成查询。所有表的列表都在sys.tables中。
#2
4
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.
Proc接受两个参数:要搜索的表和要应用的标准。您可以将主子句和where子句传递给第二个参数。我写了proc解释双引号回到单引号....这也是基于最初的开发人员概念。
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'
#3
4
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:
- 在SSMS中运行此脚本并选择结果窗格中的所有行:
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: - 将结果粘贴到一个新的查询窗口中。滚动到最底部,并删除后面的UNION ALL语句。它看起来是这样的:
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.
- 运行该查询。在一个300列的数据库上运行大约需要6分钟。这将取决于使用了多少索引,是快还是慢。
#4
2
This is way too useful not to be put into a handy little system proc - especially if you've just inherited a legacy database, and are wondering what columns you can drop or ignore.
这是非常有用的方法,不应该放在一个方便的小系统proc中—特别是如果您刚刚继承了一个遗留数据库,并且想知道可以删除或忽略哪些列。
/*
Show the count of not-null values in a table
*/
create proc sp_aaShowAllNullColumns @tableName varchar(255) as
begin
set nocount on
declare @sql nvarchar(4000)
declare @cols nvarchar(4000)
declare @tcols table( colbit nvarchar(255) )
insert @tcols
select 'count(' + name + ') as ' + name + ', ' as colbit
from sys.columns
where object_id = object_id(@tableName)
and is_nullable = 1
select @cols = coalesce( @cols, ', ', '' ) + colbit from @tcols
select @cols = substring( @cols, 1, (len(@cols) - 1) )
select @cols = isnull( @cols, '' )
select @sql = 'select count(*) as Rows' + @cols + ' from ' + @tableName
exec sp_executeSql @sql
end
go
exec sys.sp_MS_marksystemobject 'sp_aaShowAllNullColumns'
go
use Bookshop
go
exec sp_aaShowAllNullColumns 'Books'
go