Vous voulez dire une table particulière ou toutes les tables d'un schéma?
Jack Douglas
1
Pourquoi auriez-vous besoin de faire ça? On dirait que vous avez trop de colonnes / tableaux et que vous devriez repenser votre conception.
eevar
Réponses:
13
banc d'essai:
create role stack;createschemaauthorization stack;set role stack;createtable my_table asselect generate_series(0,9)as id,1as val1,null::integer as val2;createtable my_table2 asselect generate_series(0,9)as id,1as val1,null::integer as val2,3as val3;
une fonction:
createfunction has_nonnulls(p_schema in text, p_table in text, p_column in text)
returns boolean language plpgsql as$$declare
b boolean;beginexecute'select exists(select * from '||
p_table||' where '||p_column||' is not null)'into b;return b;end;$$;
requete:
select table_schema, table_name, column_name,
has_nonnulls(table_schema, table_name, column_name)from information_schema.columns
where table_schema='stack';
résultat:
table_schema | table_name | column_name | has_nonnulls
--------------+------------+-------------+--------------
stack | my_table | id | t
stack | my_table | val1 | t
stack | my_table | val2 | f
stack | my_table2 | id | t
stack | my_table2 | val1 | t
stack | my_table2 | val2 | f
stack | my_table2 | val3 | t
(7rows)
De plus, vous pouvez obtenir une réponse approximative en interrogeant le catalogue - si null_fracest zéro qui n'indique pas de null mais doit être revérifié par rapport aux données «réelles»:
C'est une vieille question, mais les gens qui utilisent des extensions spatiales (postgis) doivent noter que les colonnes spatiales vides n'apparaissent pas pg_statssi elles sont vides lors de la création de la table. J'ai découvert cela aujourd'hui en faisant du ménage. J'ai découvert que certaines tables aspatiales historiques avaient été importées à l'aide de ogr2ogr. s'il n'y a pas de colonne spatiale dans les données importées, ogr2ogrcrée une colonne de géométrie pleine de <NULL>. My pg_statsn'a pas de colonnes de géométrie des tables aspatiales importées (il a toutes les autres colonnes pour ces tables). Assez étrange, je pensais.
GT.
6
Dans Postgresql, vous pouvez obtenir les données directement à partir des statistiques:
vacuum analyze;-- if neededselect schemaname, tablename, attname
from pg_stats
where most_common_vals isnulland most_common_freqs isnulland histogram_bounds isnulland correlation isnulland null_frac =1;
Vous pourriez obtenir quelques faux positifs, donc une nouvelle vérification est en ordre après avoir trouvé les candidats.
Avez-vous besoin d'autres conditions que null_frac=1?
Jack Douglas
Je ne suis pas sûr. null_frac est vraisemblablement un réel, il se peut donc qu'il arrondisse à 1 dans certains cas étranges. Mais même avec 1 sur 10 000 lignes, cela aboutirait à quelque chose qui convient.
Denis de Bernardy
1
Je vais vous montrer ma solution en T-SQL, travaillant pour SQL Server 2008. Je ne connais pas PostgreSQL, mais j'espère que vous trouverez quelques conseils dans ma solution.
-- create test tableIF object_id ('dbo.TestTable')isnotnullDROPtable testTable
go
createtable testTable (
id int identityprimarykeyclustered,
nullColumn varchar(100)NULL,
notNullColumn varchar(100)notnull,
combinedColumn varchar(100)NULL,
testTime datetime default getdate());
go
-- insert test data:INSERTINTO testTable(nullColumn, notNullColumn, combinedColumn)SELECTNULL,'Test','Combination'from sys.objects
unionallSELECTNULL,'Test2',NULLfrom sys.objects
select*from testTable
-- FIXED SCRIPT FOR KNOWN TABLE (known structure) - find all completely NULL columnsselect sum(datalength(id))as SumColLength,'id'as ColumnName
from dbo.testTable
UNIONALLselect sum(datalength(nullColumn))as SumColLength,'nullColumn'as ColumnName
from dbo.testTable
UNIONALLselect sum(datalength(notNullColumn))as SumColLength,'notNullColumn'as ColumnName
from dbo.testTable
UNIONALLselect sum(datalength(combinedColumn))as SumColLength,'combinedColumn'as ColumnName
from dbo.testTable
UNIONALLselect sum(datalength(testTime))as SumColLength,'testTime'as ColumnName
from dbo.testTable
-- DYNAMIC SCRIPT (unknown structure) - find all completely NULL columnsdeclare@sql varchar(max)='',@tableName sysname ='testTable';SELECT@sql +='select sum(datalength('+ c.COLUMN_NAME +')) as SumColLength,
'''+ c.COLUMN_NAME +''' as ColumnName
from '+ c.TABLE_SCHEMA +'.'+ c.TABLE_NAME --as StatementToExecute+'
UNION ALL
'FROM INFORMATION_SCHEMA.COLUMNS c
WHERE c.TABLE_NAME =@tableName;SET@sql =left(@sql, len(@sql)-11)print@sql;exec(@sql);
Ce que j'ai fait, en bref, a été de créer une table de test avec 5 colonnes, ID et testTime étant générées par la fonction d'identité et getdate (), tandis que les 3 colonnes varchar sont celles qui nous intéressent. L'un n'aura que des valeurs NULL, l'un n'aura aucun NULL, l'autre sera une colonne combinée. Le résultat final du script sera que le script signalera la colonne nullColumn comme ayant toutes les lignes NULL.
L'idée était de calculer la fonction DATALENGTH pour chaque colonne (calcule le nombre d'octets pour une expression donnée). J'ai donc calculé la valeur DATALENGTH pour chaque ligne de chaque colonne et fait un SUM par colonne. Si la somme par colonne est NULL, alors la colonne complète a des lignes NULL, sinon il y a des données à l'intérieur.
Maintenant, vous devez trouver la traduction pour PostgreSQL et j'espère qu'un collègue pourra vous aider avec cela. Ou peut-être qu'il y a une belle vue du système qui montrera à quel point je suis stupide de réinventer la roue :-).
Vous devez interroger le catalogue d'informations pour ces informations:
SELECT column_name FROM information_schema.columns WHERE table_name='your_table'
vous donne les tableaux correspondants pour vos colonnes.
Je n'ai pas d'installation de postgres à portée de main mais le reste devrait être simple
loop over the results of the above query and foreach result
send a COUNT(*)to the tableif the count isnull, give back the column,else ignore it
end foreach
Cela fonctionne, mais c'est une approche itérative :-). Je préfère l'approche basée sur les ensembles.
Marian
0
Après avoir combiné à partir de plusieurs ressources, j'ai trouvé cette fonction et cette requête pour trouver toutes les colonnes vides dans toutes les tables de base de données
CREATEOR REPLACE FUNCTIONpublic.isEmptyColumn(IN table_name varchar,IN column_name varchar)
RETURNS boolean AS$$declare
count integer;BEGINexecute FORMAT('SELECT COUNT(*) from %s WHERE %s IS NOT NULL', table_name, quote_ident(column_name))into count;RETURN(count =0);END;$$
LANGUAGE PLPGSQL;SELECT s.table_name, s.column_name
FROM information_schema.columns s
WHERE(s.table_schema LIKE'public')AND(s.table_name NOTLIKE'pg_%')AND(public.isEmptyColumn(s.table_name, s.column_name))
Réponses:
banc d'essai:
une fonction:
requete:
résultat:
De plus, vous pouvez obtenir une réponse approximative en interrogeant le catalogue - si
null_frac
est zéro qui n'indique pas de null mais doit être revérifié par rapport aux données «réelles»:la source
pg_stats
si elles sont vides lors de la création de la table. J'ai découvert cela aujourd'hui en faisant du ménage. J'ai découvert que certaines tables aspatiales historiques avaient été importées à l'aide deogr2ogr
. s'il n'y a pas de colonne spatiale dans les données importées,ogr2ogr
crée une colonne de géométrie pleine de<NULL>
. Mypg_stats
n'a pas de colonnes de géométrie des tables aspatiales importées (il a toutes les autres colonnes pour ces tables). Assez étrange, je pensais.Dans Postgresql, vous pouvez obtenir les données directement à partir des statistiques:
Vous pourriez obtenir quelques faux positifs, donc une nouvelle vérification est en ordre après avoir trouvé les candidats.
la source
null_frac=1
?Je vais vous montrer ma solution en T-SQL, travaillant pour SQL Server 2008. Je ne connais pas PostgreSQL, mais j'espère que vous trouverez quelques conseils dans ma solution.
Ce que j'ai fait, en bref, a été de créer une table de test avec 5 colonnes, ID et testTime étant générées par la fonction d'identité et getdate (), tandis que les 3 colonnes varchar sont celles qui nous intéressent. L'un n'aura que des valeurs NULL, l'un n'aura aucun NULL, l'autre sera une colonne combinée. Le résultat final du script sera que le script signalera la colonne nullColumn comme ayant toutes les lignes NULL.
L'idée était de calculer la fonction DATALENGTH pour chaque colonne (calcule le nombre d'octets pour une expression donnée). J'ai donc calculé la valeur DATALENGTH pour chaque ligne de chaque colonne et fait un SUM par colonne. Si la somme par colonne est NULL, alors la colonne complète a des lignes NULL, sinon il y a des données à l'intérieur.
Maintenant, vous devez trouver la traduction pour PostgreSQL et j'espère qu'un collègue pourra vous aider avec cela. Ou peut-être qu'il y a une belle vue du système qui montrera à quel point je suis stupide de réinventer la roue :-).
la source
Vous devez interroger le catalogue d'informations pour ces informations:
vous donne les tableaux correspondants pour vos colonnes.
Je n'ai pas d'installation de postgres à portée de main mais le reste devrait être simple
la source
Après avoir combiné à partir de plusieurs ressources, j'ai trouvé cette fonction et cette requête pour trouver toutes les colonnes vides dans toutes les tables de base de données
Prendre plaisir :)
la source