it-swarm-vi.tech

SQL: Chọn các cột chỉ có giá trị NULL

Làm cách nào để tôi chọn tất cả các cột trong bảng chỉ chứa giá trị NULL cho tất cả các hàng? Tôi đang sử dụng MS SQL Server 2005 . Tôi đang cố gắng tìm ra những cột nào không được sử dụng trong bảng để tôi có thể xóa chúng.

44
Bryan Roth

Đây là phiên bản sql 2005 trở lên: Thay thế ADDR_Address bằng tablename của bạn.

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
61
Charles Graham
SELECT cols
FROM table
WHERE cols IS NULL
22
Eight Characters

Điều này sẽ cung cấp cho bạn một danh sách tất cả các cột trong bảng "Người" chỉ có các giá trị NULL. Bạn sẽ nhận được kết quả dưới dạng nhiều tập kết quả, trống hoặc chứa tên của một cột. Bạn cần thay thế "Người" ở hai nơi để sử dụng nó với một bảng khác.

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
5
MobyDX

Hoặc bạn có muốn xem liệu một cột chỉ có các giá trị NULL (và, do đó, có lẽ không được sử dụng)?

Làm rõ thêm về câu hỏi có thể giúp đỡ.

EDIT: Ok .. đây là một số mã thực sự thô sơ để giúp bạn đi ...

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 @[email protected]@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

Vâng, có những cách dễ dàng hơn, nhưng tôi có một cuộc họp để đi đến ngay bây giờ. Chúc may mắn!

3
Kevin Fairchild

Bạn có thể làm: 

select 
  count(<columnName>)
from
  <tableName>

Nếu số đếm trả về 0 có nghĩa là tất cả các hàng trong cột đó đều là NULL (hoặc không có hàng nào trong bảng)

có thể thay đổi thành 

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

Nếu bạn muốn tự động hóa nó, bạn có thể sử dụng các bảng hệ thống để lặp lại các tên cột trong bảng mà bạn quan tâm

2
kristof

Đây là phiên bản cập nhật của truy vấn của Bryan cho năm 2008 trở về sau. Nó sử dụng Information_SCHema.COLUMNS, thêm các biến cho lược đồ bảng và tên bảng. Kiểu dữ liệu cột đã được thêm vào đầu ra. Bao gồm loại dữ liệu cột giúp khi tìm kiếm một cột của một loại dữ liệu cụ thể. Tôi đã không thêm chiều rộng cột hoặc bất cứ điều gì.

Đối với đầu ra RAISERROR ... VỚI NOWAIT được sử dụng để văn bản sẽ hiển thị ngay lập tức thay vì tất cả cùng một lúc (đối với hầu hết các phần) ở cuối như 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;

2
user2466387

Không thực sự chắc chắn về năm 2005, nhưng năm 2008 đã ăn nó:

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)
1
user8120267

Tôi cũng khuyên bạn nên tìm kiếm các trường có cùng giá trị, không chỉ NULL.

Đó là, đối với mỗi cột trong mỗi bảng, hãy thực hiện truy vấn:

SELECT COUNT(DISTINCT field) FROM tableName

và tập trung vào những kết quả trả về 1.

1
squadette

Nếu bạn cần liệt kê tất cả các hàng trong đó tất cả các giá trị cột là NULL, thì tôi sẽ sử dụng hàm COLLATE. Cái này lấy một danh sách các giá trị và trả về giá trị khác null đầu tiên. Nếu bạn thêm tất cả các tên cột vào danh sách, sau đó sử dụng IS NULL, bạn sẽ nhận được tất cả các hàng chỉ chứa null.

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

Bạn thực sự không nên có bất kỳ bảng nào có TẤT CẢ columns null, vì điều này có nghĩa là bạn không có primary key (không được phép là null). Không có khóa chính là điều cần tránh; Điều này phá vỡ hình thức bình thường đầu tiên.

1
The Doc
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;
0
user3827049

Phiên bản cập nhật của phiên bản 'user2466387', với một thử nghiệm nhỏ bổ sung có thể cải thiện hiệu suất, bởi vì việc kiểm tra các cột không rỗng là vô ích:

AND IS_NULLABLE = 'YES'

Mã đầy đủ:

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;
0
Sylvain Bruyere

Thử đi -

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)
0
Jasmina Shevchenko

Bạn sẽ phải lặp lại tập hợp các cột và kiểm tra từng cột. Bạn sẽ có thể nhận được một danh sách tất cả các cột bằng lệnh bảng MÔ TẢ.

Mã giả:


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;

Tôi biết điều này có vẻ hơi trực quan nhưng SQL không cung cấp phương thức chọn cột, chỉ các hàng.

0
Daniel Papasian