SQL:仅选择具有NULL值的列

时间:2020-03-05 18:53:34  来源:igfitidea点击:

如何选择表中所有行仅包含NULL值的所有列?我正在使用MS SQL Server2005. 我试图找出表中未使用的列,因此可以删除它们。

解决方案

回答

SELECT cols
FROM table
WHERE cols IS NULL

回答

我们可能需要澄清一下。我们真正要完成的任务是什么?如果我们真的想找出仅包含空值的列名,那么我们将不得不遍历scheama并基于此进行动态查询。

我不知道我们使用的是哪个DBMS,因此我将在此处放置一些伪代码。

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

回答

还是只想查看一列是否只有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

是的,有更简单的方法,但是我现在要开会。祝你好运!

回答

我们必须遍历一组列并检查每个列。我们应该能够使用DESCRIBE table命令获得所有列的列表。

伪代码:

可以更改为

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;

I know this seems a little counterintuitive but SQL does not provide a native method of selecting columns, only rows.

Answer

You can do: 

select 
  count(<columnName>)
from
  <tableName>

如果要使其自动化,则可以使用系统表来迭代我们感兴趣的表中的列名

回答

我还建议搜索所有具有相同值的字段,而不仅仅是NULL。

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

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

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

回答

这应该为我们提供表" Person"中所有列只有NULL值的列表。我们将获得多个结果集的结果,这些结果集为空或者包含单个列的名称。我们需要在两个地方替换" Person"才能将其与另一个表一起使用。

SELECT COUNT(DISTINCT field) FROM tableName

回答

这是sql 2005或者更高版本:用表名替换ADDR_Address。

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的所有行,那么我将使用COLLATE函数。这将获取值列表,并返回第一个非空值。如果将所有列名添加到列表中,然后使用" IS NULL",则应该获得仅包含空值的所有行。

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

我们实际上不应该有任何表的所有columns为空,因为这意味着我们没有primary key(不允许为null)。没有主键是可以避免的。这会破坏第一个范式。

代码数量不匹配