PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Fonction PLpgSQL pour trouver des colonnes avec uniquement des valeurs NULL dans une table donnée

Vous pouvez interroger la table du catalogue pg_attribute pour obtenir une liste des colonnes qui ne sont pas définies NOT NULL et donc peut maintenir NULL valeurs :

SELECT quote_ident(attname) AS column_can_be_null
FROM   pg_attribute
WHERE  attrelid = 'tbl'::regclass -- valid, visible table name 
AND    attnum >= 1                -- exclude tableoid & friends
AND    NOT attisdropped           -- exclude dropped columns
AND    NOT attnotnull             -- exclude columns defined NOT NULL!
ORDER  BY attnum;

tbl est le nom de votre table (éventuellement qualifié par le schéma).

Ne dit pas qu'il y a des valeurs NULL réelles dans la colonne. Il faudrait tester chaque colonne. Comme ceci :

Automatisation complète avec la fonction plpgsql

CREATE OR REPLACE FUNCTION f_all_null_columns_of_tbl(_tbl regclass)
  RETURNS SETOF text AS
$func$
DECLARE
   _row_ct  bigint;        -- count rows in table $1
   _sql     text;          -- SQL string to test for NULL values
   _cols    text[];        -- array of candidate column names
   _nulls   bool[];        -- array of test results
BEGIN

EXECUTE 'SELECT count(*) FROM ' || _tbl
INTO _row_ct;

IF _row_ct = 0 THEN
   RAISE EXCEPTION 'Table % has no rows!', _tbl;  -- pointless for empty table
ELSE
   RAISE NOTICE '% rows in table %.', _row_ct, _tbl; 
END IF;

SELECT INTO _sql, _cols
      'SELECT ARRAY[' || string_agg('bool_and(' || col || ' IS NULL)', ', ')
       || '] FROM ' || _tbl
    , array_agg(col)
FROM  (
   SELECT quote_ident(attname) AS col
   FROM   pg_attribute
   WHERE  attrelid = _tbl            -- valid, visible table name 
   AND    attnum >= 1                -- exclude tableoid & friends
   AND    NOT attisdropped           -- exclude dropped columns
   AND    NOT attnotnull             -- exclude columns defined NOT NULL!
   ORDER  BY attnum
   ) sub;

EXECUTE _sql INTO _nulls;

FOR i IN 1 .. array_upper(_cols, 1)
LOOP
   IF _nulls[i] THEN                 -- column is NULL in all rows
      RETURN NEXT _cols[i];
   END IF;
END LOOP;

RETURN;
END
$func$ LANGUAGE plpgsql;

Appel :

SELECT f_all_null_columns_of_tbl('my_schema.my_table');

Testé avec Postgres 9.1 et 9.3.
Il utilise un certain nombre de fonctionnalités plpgsql avancées.

SQL Fiddle.

Réponse connexe en construisant du code SQL et en l'exécutant, avec une syntaxe moderne :

À propos du parcours d'un enregistrement :