it-swarm-tr.com

SQL: Yalnızca NULL değerine sahip sütunları seçin

Tablodaki tüm sütunları yalnızca tüm satırlar için NULL değer içeren nasıl seçerim? MS SQL Server 2005 kullanıyorum. Tabloda hangi sütunların kullanılmadığını bulmaya çalışıyorum, böylece onları silebilirim.

44
Bryan Roth

İşte sql 2005 veya daha sonraki bir sürüm: ADDR_Adresi, tablen adınızla değiştirin.

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

Bu, "NULL" değerlerine sahip "Person" tablosundaki tüm sütunların bir listesini vermelidir. Sonuçları boş veya tek bir sütunun adını içeren birden fazla sonuç kümesi olarak alırsınız. Başka bir tabloyla kullanmak için "Kişi" yi iki yerde değiştirmeniz gerekir.

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

Yoksa sadece bir sütunda NULL değerlerin olup olmadığını görmek ister misiniz (ve dolayısıyla muhtemelen kullanılmaz)?

Sorunun daha fazla açıklığa kavuşturulması yardımcı olabilir.

EDIT: Tamam .. işte size gitmeniz için bazı zorlu kodlar ...

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

Evet, daha kolay yollar var, ama şu an gidecek bir toplantım var. İyi şanslar!

3
Kevin Fairchild

Yapabilirsin: 

select 
  count(<columnName>)
from
  <tableName>

Sayım 0 döndürürse, bu, bu sütundaki tüm satırların tümü NULL anlamına gelir (veya tabloda hiç satır yoktur).

olarak değiştirilebilir 

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

Otomatikleştirmek istiyorsanız, ilgilendiğiniz tablodaki sütun adlarını yinelemek için sistem tablolarını kullanabilirsiniz.

2
kristof

İşte Bryan'ın 2008 ve daha sonraki arama sorgusunun güncellenmiş bir versiyonu. INFORMATION_SCHEMA.COLUMNS kullanır, tablo şeması ve tablo adı için değişkenler ekler. Sütun veri türü çıktıya eklendi. Sütun veri türünü dahil etmek, belirli bir veri türünde bir sütun ararken yardımcı olur. Sütun genişliklerini veya başka bir şey eklemedim.

RAISERROR ... WITH NOWAIT çıktısı için kullanılır, böylece PRINT'in yaptığı gibi metin bir anda (çoğunlukla) derhal hemen görüntülenir.

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

Aslında 2005'ten emin değilim, ancak 2008 bunu yedi:

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

Sadece NULL değil, hepsinin değerinin aynı olduğu alanları aramanızı da tavsiye ederim.

Yani, her tablodaki her sütun için sorguyu yapın:

SELECT COUNT(DISTINCT field) FROM tableName

ve sonuç olarak 1'i geri getirenlere konsantre olun.

1
squadette

Tüm sütun değerlerinin NULL olduğu tüm satırları listelemeniz gerekirse, COLLATE işlevini kullanırdım. Bu, değerlerin bir listesini alır ve ilk boş olmayan değeri döndürür. Tüm sütun adlarını listeye eklerseniz, sonra IS NULL kullanın, sadece null içeren tüm satırları almalısınız.

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

Gerçekten de columns null değerinde ALL içeren bir tabloya sahip olmamalısınız, çünkü bu bir primary key 'a sahip olmadığınız anlamına gelir (null olmasına izin verilmez). Birincil anahtara sahip olmamak kaçınılması gereken bir şeydir; bu ilk normal formu kırar.

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

'Kullanıcı2466387' sürümünün güncellenmiş bir sürümü, performansı artırabilecek ek bir küçük sınamaya sahip;

AND IS_NULLABLE = 'YES'

Kodun tamamı:

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

Bunu dene -

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

Sütun kümesi üzerinde döngü yapmanız ve her birini kontrol etmeniz gerekir. Bir DESCRIBE table komutu ile tüm sütunların bir listesini elde edebilmeniz gerekir.

Sözde kod:


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;

Bunun biraz zamanlayıcı göründüğünü biliyorum, ancak SQL sütunların seçilmesi için yerel bir yöntem sunmuyor, yalnızca satırlar sunuyor.

0
Daniel Papasian