Comment sélectionner toutes les colonnes d'une table contenant uniquement des valeurs NULL pour toutes les lignes? J'utilise MS SQL Server 2005 . J'essaie de savoir quelles colonnes ne sont pas utilisées dans le tableau afin de pouvoir les supprimer.
Voici la version 2005 ou ultérieure de SQL 2005: Remplacez ADDR_Address par votre nom de fichier.
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
Cela devrait vous donner une liste de toutes les colonnes de la table "Personne" qui ne contient que des valeurs NULL. Vous obtiendrez les résultats sous forme de plusieurs ensembles de résultats, vides ou contenant le nom d'une seule colonne. Vous devez remplacer "Personne" à deux endroits pour l'utiliser avec une autre table.
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
Ou voulez-vous simplement voir si une colonne ne contient que des valeurs NULL (et est donc probablement inutilisée)?
Des précisions supplémentaires sur la question pourraient être utiles.
EDIT: .__ Ok. Voici un code très approximatif pour vous aider à démarrer ...
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
Oui, il existe des moyens plus faciles, mais j'ai une réunion à laquelle assister maintenant. Bonne chance!
Tu peux faire:
select
count(<columnName>)
from
<tableName>
Si le nombre retourne 0, cela signifie que toutes les lignes de cette colonne sont toutes NULL (ou qu'il n'y a aucune ligne dans la table).
peut être changé en
select
case(count(<columnName>)) when 0 then 'Nulls Only' else 'Some Values' end
from
<tableName>
Si vous souhaitez l’automatiser, vous pouvez utiliser les tables système pour itérer les noms de colonne de la table qui vous intéresse.
Voici une version mise à jour de la requête de Bryan pour 2008 et les versions ultérieures. Il utilise INFORMATION_SCHEMA.COLUMNS, ajoute des variables pour le schéma et le nom de la table. Le type de données de la colonne a été ajouté à la sortie. L'inclusion du type de données de colonne facilite la recherche d'une colonne d'un type de données particulier. Je n'ai pas ajouté les largeurs de colonne ou quoi que ce soit.
RAISERROR ... WITH NOWAIT est utilisé pour que le texte s'affiche immédiatement au lieu de tout à la fois (pour la plupart) à la fin, comme le fait 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;
Pas vraiment sûr de 2005, mais 2008 l'a mangé:
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)
Je recommanderais également de rechercher des champs qui ont tous la même valeur, pas seulement NULL.
Autrement dit, pour chaque colonne de chaque table, effectuez la requête:
SELECT COUNT(DISTINCT field) FROM tableName
et se concentrer sur ceux qui retournent 1 à la suite.
Si vous avez besoin de lister toutes les lignes où toutes les valeurs de colonne sont NULL
, alors j'utiliserais la fonction COLLATE
. Cela prend une liste de valeurs et retourne la première valeur non NULL. Si vous ajoutez tous les noms de colonne à la liste, puis utilisez IS NULL
, vous devriez obtenir toutes les lignes contenant uniquement des valeurs NULL.
SELECT * FROM MyTable WHERE COLLATE(Col1, Col2, Col3, Col4......) IS NULL
Vous ne devriez pas vraiment avoir de table avec TOUTES les columns
null, car cela signifie que vous n'avez pas de primary key
(non autorisé à être null
). Ne pas avoir de clé primaire est quelque chose à éviter. cela casse la première forme normale.
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;
Une version mise à jour de la version 'user2466387', avec un petit test supplémentaire qui peut améliorer les performances, car il est inutile de tester des colonnes non nullables:
AND IS_NULLABLE = 'YES'
Le code complet:
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;
Essaye ça -
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)
Vous devrez parcourir l'ensemble des colonnes et vérifier chacune d'elles. Vous devriez pouvoir obtenir une liste de toutes les colonnes avec une commande de table DESCRIBE.
Pseudo-code:
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;
Je sais que cela semble un peu contre-intuitif, mais SQL ne fournit pas de méthode native pour sélectionner des colonnes, mais uniquement des lignes.