すべての行にNULL値のみを含むテーブルのすべての列を選択するにはどうすればよいですか? MS SQL Server 2005を使用しています。テーブルで使用されていない列を見つけて削除できるようにしています。
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
SELECT cols
FROM table
WHERE cols IS NULL
これにより、NULL値のみを持つテーブル「Person」のすべての列のリストが表示されます。結果は複数の結果セットとして取得されます。結果セットは空であるか、単一の列の名前を含んでいます。別のテーブルで使用するには、「Person」を2か所で置き換える必要があります。
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
以下は、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;
または、列にNULL値しか含まれていない(したがって、おそらく未使用である)かどうかだけを見たいですか?
質問をさらに明確にすると役立つかもしれません。
編集: OK.
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>
カウントが0を返す場合、その列のすべての行がすべてNULL(またはテーブルに行がまったくない)であることを意味します
に変更できます
select
case(count(<columnName>)) when 0 then 'Nulls Only' else 'Some Values' end
from
<tableName>
自動化する場合は、システムテーブルを使用して、目的のテーブルの列名を反復処理できます。
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)
NULLだけでなく、すべて同じ値を持つフィールドを検索することもお勧めします。
つまり、各テーブルの各列に対してクエリを実行します。
SELECT COUNT(DISTINCT field) FROM tableName
結果として1を返すものに集中します。
すべての列の値がNULL
であるすべての行をリストする必要がある場合は、COLLATE
関数を使用します。これは値のリストを取り、最初の非ヌル値を返します。すべての列名をリストに追加する場合は、IS NULL
、ヌルのみを含むすべての行を取得する必要があります。
SELECT * FROM MyTable WHERE COLLATE(Col1, Col2, Col3, Col4......) IS NULL
columns
nullがすべて含まれるテーブルは実際にはないはずです。これは、primary key
(null
にはできません)。主キーがないことは避けるべきものです。これは最初の正規形を壊します。
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」バージョンの更新バージョン。追加の小さなテストにより、パフォーマンスを向上させることができます。これは、nullを許可しない列をテストするのに役に立たないためです。
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;
これを試して -
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)
列のセットをループして、各列をチェックする必要があります。 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;
私はこれが少し直感に反しているように見えますが、SQLは列を選択するネイティブな方法を提供せず、行のみを提供します。