SQL:仅select具有NULL值的列

如何select只包含所有行的空值的表中的所有列? 我正在使用MS SQL Server 2005 。 我试图找出哪些列没有在表中使用,所以我可以删除它们。

这里是SQL 2005或更高版本:用您的表名replaceADDR_Address。

declare @col varchar(255), @cmd varchar(max) DECLARE getinfo cursor for SELECT c.name FROM sys.tables t JOIN sys.columns c ON t.Object_ID = c.Object_ID WHERE t.Name = 'ADDR_Address' OPEN getinfo FETCH NEXT FROM getinfo into @col WHILE @@FETCH_STATUS = 0 BEGIN SELECT @cmd = 'IF NOT EXISTS (SELECT top 1 * FROM ADDR_Address WHERE [' + @col + '] IS NOT NULL) BEGIN print ''' + @col + ''' end' EXEC(@cmd) FETCH NEXT FROM getinfo into @col END CLOSE getinfo DEALLOCATE getinfo 
 SELECT cols FROM table WHERE cols IS NULL 

这应该给你一个只有NULL值的表“Person”的所有列的列表。 您将以多个结果集的forms获得结果,这些结果集是空的或包含单个列的名称。 您需要在两个地方replace“Person”,以便与另一个表一起使用。

 DECLARE crs CURSOR LOCAL FAST_FORWARD FOR SELECT name FROM syscolumns WHERE id=OBJECT_ID('Person') OPEN crs DECLARE @name sysname FETCH NEXT FROM crs INTO @name WHILE @@FETCH_STATUS = 0 BEGIN EXEC('SELECT ''' + @name + ''' WHERE NOT EXISTS (SELECT * FROM Person WHERE ' + @name + ' IS NOT NULL)') FETCH NEXT FROM crs INTO @name END CLOSE crs DEALLOCATE crs 

或者你想只看看一列只有NULL值(因此,可能未使用)?

进一步澄清这个问题可能会有所帮助。

编辑:好的..这里有一些非常粗糙的代码让你去…

 SET NOCOUNT ON DECLARE @TableName Varchar(100) SET @TableName='YourTableName' CREATE TABLE #NullColumns (ColumnName Varchar(100), OnlyNulls BIT) INSERT INTO #NullColumns (ColumnName, OnlyNulls) SELECT c.name, 0 FROM syscolumns c INNER JOIN sysobjects o ON c.id = o.id AND o.name = @TableName AND o.xtype = 'U' DECLARE @DynamicSQL AS Nvarchar(2000) DECLARE @ColumnName Varchar(100) DECLARE @RC INT SELECT TOP 1 @ColumnName = ColumnName FROM #NullColumns WHERE OnlyNulls=0 WHILE @@ROWCOUNT > 0 BEGIN SET @RC=0 SET @DynamicSQL = 'SELECT TOP 1 1 As HasNonNulls FROM ' + @TableName + ' (nolock) WHERE ''' + @ColumnName + ''' IS NOT NULL' EXEC sp_executesql @DynamicSQL set @RC=@@rowcount IF @RC=1 BEGIN SET @DynamicSQL = 'UPDATE #NullColumns SET OnlyNulls=1 WHERE ColumnName=''' + @ColumnName + '''' EXEC sp_executesql @DynamicSQL END ELSE BEGIN SET @DynamicSQL = 'DELETE FROM #NullColumns WHERE ColumnName=''' + @ColumnName+ '''' EXEC sp_executesql @DynamicSQL END SELECT TOP 1 @ColumnName = ColumnName FROM #NullColumns WHERE OnlyNulls=0 END SELECT * FROM #NullColumns DROP TABLE #NullColumns SET NOCOUNT OFF 

是的,有更简单的方法,但我现在有一个会议去。 祝你好运!

你可以做:

 select count(<columnName>) from <tableName> 

如果count返回0意味着该列中的所有行全部为NULL(或者表中根本没有行)

可以改成

 select case(count(<columnName>)) when 0 then 'Nulls Only' else 'Some Values' end from <tableName> 

如果你想自动化它,你可以使用系统表遍历你感兴趣的表中的列名

这是Bryan 2008年及以后版本查询的更新版本。 它使用INFORMATION_SCHEMA.COLUMNS,为表模式和表名添加variables。 列数据types已添加到输出中。 包含列数据types有助于查找特定数据types的列。 我没有添加列的宽度或任何东西。

为了输出RAISERROR …使用NOWAIT,所以文本将立即显示,而不是像PRINT那样一次显示(大部分)。

 SET NOCOUNT ON; DECLARE @ColumnName sysname ,@DataType nvarchar(128) ,@cmd nvarchar(max) ,@TableSchema nvarchar(128) = 'dbo' ,@TableName sysname = 'TableName'; DECLARE getinfo CURSOR FOR SELECT c.COLUMN_NAME ,c.DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS AS c WHERE c.TABLE_SCHEMA = @TableSchema AND c.TABLE_NAME = @TableName; OPEN getinfo; FETCH NEXT FROM getinfo INTO @ColumnName, @DataType; WHILE @@FETCH_STATUS = 0 BEGIN SET @cmd = N'IF NOT EXISTS (SELECT * FROM ' + @TableSchema + N'.' + @TableName + N' WHERE [' + @ColumnName + N'] IS NOT NULL) RAISERROR(''' + @ColumnName + N' (' + @DataType + N')'', 0, 0) WITH NOWAIT;'; EXECUTE (@cmd); FETCH NEXT FROM getinfo INTO @ColumnName, @DataType; END; CLOSE getinfo; DEALLOCATE getinfo; 

我也build议search所有具有相同值的字段,而不仅仅是NULL。

也就是说,对于每个表中的每个列执行查询:

 SELECT COUNT(DISTINCT field) FROM tableName 

并专注于那些返回1的结果。

如果您需要列出所有列值为NULL所有行,那么我会使用COLLATE函数。 这将获取值列表并返回第一个非空值。 如果将所有列名称添加到列表中,则使用IS NULL ,您应该获得仅包含空值的所有行。

 SELECT * FROM MyTable WHERE COLLATE(Col1, Col2, Col3, Col4......) IS NULL 

你不应该真的有任何表的所有列为空,因为这意味着你没有一个primary key (不允许为null )。 没有主键是需要避免的。 这打破了第一个正常的forms。

你可能需要澄清一点。 你真的想完成什么? 如果你真的想找出只包含空值的列名,那么你将不得不遍历模式,并根据这个dynamic查询。

我不知道你正在使用哪个DBMS,所以我会在这里放一些伪代码。

 for each col begin @cmd = 'if not exists (select * from tablename where ' + col + ' is not null begin print ' + col + ' end' exec(@cmd) end 

你将不得不遍历一组列,并检查每一个。 您应该能够使用DESCRIBE表命令获取所有列的列表。

伪代码:

 foreach $column ($cols) { query("SELECT count(*) FROM table WHERE $column IS NOT NULL") if($result is zero) { # $column contains only null values" push @onlyNullColumns, $column; } else { # $column contains non-null values } } return @onlyNullColumns; 

我知道这似乎有点违反直觉,但SQL不提供select列,只有行的本地方法。

尝试这个 –

 DECLARE @table VARCHAR(100) = 'dbo.table' DECLARE @sql NVARCHAR(MAX) = '' SELECT @sql = @sql + 'IF NOT EXISTS(SELECT 1 FROM ' + @table + ' WHERE ' + c.name + ' IS NOT NULL) PRINT ''' + c.name + '''' FROM sys.objects o JOIN sys.columns c ON o.[object_id] = c.[object_id] WHERE o.[type] = 'U' AND o.[object_id] = OBJECT_ID(@table) AND c.is_nullable = 1 EXEC(@sql) 
 SELECT t.column_name FROM user_tab_columns t WHERE t.nullable = 'Y' AND t.table_name = 'table name here' AND t.num_distinct = 0; 

“user2466387”版本的更新版本,另外还有一个可以提高性能的小testing,因为testing不可空列是没用的:

 AND IS_NULLABLE = 'YES' 

完整的代码:

 SET NOCOUNT ON; DECLARE @ColumnName sysname ,@DataType nvarchar(128) ,@cmd nvarchar(max) ,@TableSchema nvarchar(128) = 'dbo' ,@TableName sysname = 'TableName'; DECLARE getinfo CURSOR FOR SELECT c.COLUMN_NAME ,c.DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS AS c WHERE c.TABLE_SCHEMA = @TableSchema AND c.TABLE_NAME = @TableName AND IS_NULLABLE = 'YES'; OPEN getinfo; FETCH NEXT FROM getinfo INTO @ColumnName, @DataType; WHILE @@FETCH_STATUS = 0 BEGIN SET @cmd = N'IF NOT EXISTS (SELECT * FROM ' + @TableSchema + N'.' + @TableName + N' WHERE [' + @ColumnName + N'] IS NOT NULL) RAISERROR(''' + @ColumnName + N' (' + @DataType + N')'', 0, 0) WITH NOWAIT;'; EXECUTE (@cmd); FETCH NEXT FROM getinfo INTO @ColumnName, @DataType; END; CLOSE getinfo; DEALLOCATE getinfo; 

实际上并不确定2005年,但2008年吃了它:

 USE [DATABASE_NAME] -- ! GO DECLARE @SQL NVARCHAR(MAX) DECLARE @TableName VARCHAR(255) SET @TableName = 'TABLE_NAME' -- ! SELECT @SQL = ( SELECT CHAR(10) +'DELETE FROM ['+t1.TABLE_CATALOG+'].['+t1.TABLE_SCHEMA+'].['+t1.TABLE_NAME+'] WHERE ' +( SELECT CASE t2.ORDINAL_POSITION WHEN (SELECT MIN(t3.ORDINAL_POSITION) FROM INFORMATION_SCHEMA.COLUMNS t3 WHERE t3.TABLE_NAME=t2.TABLE_NAME) THEN '' ELSE 'AND ' END +'['+COLUMN_NAME+'] IS NULL' AS 'data()' FROM INFORMATION_SCHEMA.COLUMNS t2 WHERE t2.TABLE_NAME=t1.TABLE_NAME FOR XML PATH('') ) AS 'data()' FROM INFORMATION_SCHEMA.TABLES t1 WHERE t1.TABLE_NAME = @TableName FOR XML PATH('') ) SELECT @SQL -- EXEC(@SQL)