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

Définir les chaînes vides ('') sur NULL dans toute la base de données

Le moyen le plus efficace d'y parvenir :

  • Exécuter une seule UPDATE par tableau.
  • Mettre à jour uniquement les colonnes nullables (non définies NOT NULL ) avec n'importe quelle chaîne vide réelle.
  • Ne mettez à jour que les lignes avec une chaîne vide réelle.
  • Laissez les autres valeurs inchangées.

Cette réponse connexe a une fonction plpgsql qui construit et exécute le UPDATE commande utilisant le catalogue système pg_attribute automatiquement et en toute sécurité pour une table donnée :

  • Remplacer les chaînes vides par des valeurs nulles

Utilisation de la fonction f_empty2null() à partir de cette réponse, vous pouvez parcourir les tables sélectionnées comme ceci :

DO
$do$
DECLARE
   _tbl regclass;
BEGIN
   FOR _tbl IN
      SELECT c.oid::regclass
      FROM   pg_class c
      JOIN   pg_namespace n ON n.oid = c.relnamespace
      WHERE  c.relkind = 'r'            -- only regular tables
      AND    n.nspname NOT LIKE 'pg_%'  -- exclude system schemas
   LOOP
      RAISE NOTICE $$PERFORM f_empty2null('%');$$, _tbl;
      -- PERFORM f_empty2null(_tbl);  -- uncomment to prime the bomb
   END LOOP;
END
$do$;

Attention ! Cela met à jour toutes les chaînes vides dans toutes les colonnes de toutes les tables utilisateur de la base de données. Assurez-vous que c'est ce que vous voulez ou cela pourrait détruire votre base de données.

Vous avez besoin de UPDATE privilèges sur toutes les tables sélectionnées, bien sûr.

En tant que dispositif de sécurité pour enfants, j'ai commenté la charge utile.

Vous avez peut-être remarqué que j'utilise directement les catalogues système, pas le schéma d'informations (qui fonctionnerait également). À propos de ceci :

  • Comment vérifier si une table existe dans un schéma donné
  • Requête pour renvoyer les noms des colonnes de sortie et les types de données d'une requête, d'une table ou d'une vue

Pour une utilisation répétée

Voici une solution intégrée pour une utilisation répétée. Sans dispositifs de sécurité :

CREATE OR REPLACE FUNCTION f_all_empty2null(OUT _tables int, OUT _rows int) AS
$func$
DECLARE
   _typ CONSTANT regtype[] := '{text, bpchar, varchar, \"char\"}';
   _sql text;
   _row_ct int;
BEGIN
   _tables := 0;  _rows := 0;
   FOR _sql IN
      SELECT format('UPDATE %s SET %s WHERE %s'
                  , t.tbl
                  , string_agg(format($$%1$s = NULLIF(%1$s, '')$$, t.col), ', ')
                  , string_agg(t.col || $$ = ''$$, ' OR '))
      FROM  (
         SELECT c.oid::regclass AS tbl, quote_ident(attname) AS col
         FROM   pg_namespace n
         JOIN   pg_class     c ON c.relnamespace = n.oid
         JOIN   pg_attribute a ON a.attrelid = c.oid
         WHERE  n.nspname NOT LIKE 'pg_%'   -- exclude system schemas
         AND    c.relkind = 'r'             -- only regular tables
         AND    a.attnum >= 1               -- exclude tableoid & friends
         AND    NOT a.attisdropped          -- exclude dropped columns
         AND    NOT a.attnotnull            -- exclude columns defined NOT NULL!
         AND    a.atttypid = ANY(_typ)      -- only character types
         ORDER  BY a.attnum
         ) t
      GROUP  BY t.tbl
   LOOP
      EXECUTE _sql;
      GET DIAGNOSTICS _row_ct = ROW_COUNT;  -- report nr. of affected rows
      _tables := _tables + 1;
      _rows := _rows + _row_ct;
   END LOOP;
END
$func$  LANGUAGE plpgsql;

Appel :

SELECT * FROM pg_temp.f_all_empty2null();

Renvoie :

 _tables | _rows
---------+---------
 23      | 123456

Remarque comment j'ai échappé correctement les noms de table et de colonnes !

c.oid::regclass AS tbl, quote_ident(attname)  AS col

Considérez :

  • Nom de table en tant que paramètre de fonction PostgreSQL

Attention ! Même avertissement que ci-dessus.
Considérez également l'explication de base dans la réponse que j'ai liée ci-dessus :

  • Remplacer les chaînes vides par des valeurs nulles