SQL:仅选择具有NULL值的列

Bry*_*oth 49 sql-server

如何选择表中仅包含所有行的NULL值的所有列?我正在使用MS SQL Server 2005.我试图找出表中没有使用哪些列,以便我可以删除它们.

Cha*_*ham 67

这是sql 2005或更高版本:将ADDR_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
Run Code Online (Sandbox Code Playgroud)

  • 那么,我该如何做相反的事情,即仅选择具有NOT NULL值的列?在代码中将IS NOT NULL更改为IS NULL? (3认同)
  • @Steam从`WHILE`中的查询中删除`NOT`,你将得到一个列表,列中至少有一条带有值的记录. (3认同)
  • 这只是说如果没有列都是空的,那么命令成功运行而没有其他输出是预期的吗? (2认同)

小智 21

SELECT cols
FROM table
WHERE cols IS NULL
Run Code Online (Sandbox Code Playgroud)

  • 根据我对这个问题的理解,他想知道只有空值的列表. (18认同)

Mob*_*yDX 7

这应该为您提供表"Person"中仅具有NULL值的所有列的列表.您将获得多个结果集的结果,这些结果集为空或包含单个列的名称.您需要在两个位置替换"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
Run Code Online (Sandbox Code Playgroud)


Kev*_*ild 5

或者您只想查看列是否只有 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
Run Code Online (Sandbox Code Playgroud)

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


小智 5

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

对于输出,使用 RAISERROR ... WITH 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;
Run Code Online (Sandbox Code Playgroud)