PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Imposta le stringhe vuote ('') su NULL nell'intero database

Il modo più efficiente per raggiungere questo obiettivo:

  • Esegui un singolo UPDATE per tabella.
  • Aggiorna solo le colonne nullable (non definite NOT NULL ) con qualsiasi stringa vuota effettiva.
  • Aggiorna solo le righe con qualsiasi stringa vuota effettiva.
  • Lascia gli altri valori invariati.

Questa risposta correlata ha una funzione plpgsql che compila ed esegue UPDATE comando utilizzando il catalogo di sistema pg_attribute automaticamente e in sicurezza per ogni dato tavolo:

  • Sostituisci le stringhe vuote con valori null

Usando la funzione f_empty2null() da questa risposta, puoi scorrere le tabelle selezionate come questa:

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$;

Attenzione! Questo aggiorna tutte le stringhe vuote in tutte le colonne di tutte le tabelle utente nel DB. Assicurati che sia quello che vuoi o potrebbe danneggiare il tuo database.

Hai bisogno di UPDATE privilegi su tutti i tavoli selezionati, ovviamente.

Come dispositivo di sicurezza per bambini ho commentato il carico utile.

Potresti aver notato che uso direttamente i cataloghi di sistema, non lo schema delle informazioni (che funzionerebbe anche). A proposito:

  • Come verificare se esiste una tabella in un determinato schema
  • Query per restituire i nomi delle colonne di output e i tipi di dati di una query, tabella o vista

Per uso ripetuto

Ecco una soluzione integrata per un uso ripetuto. Senza dispositivi di sicurezza:

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;

Chiama:

SELECT * FROM pg_temp.f_all_empty2null();

Resi:

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

Nota come sono sfuggito correttamente ai nomi delle tabelle e delle colonne!

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

Considera:

  • Nome tabella come parametro di funzione PostgreSQL

Attenzione! Stesso avviso di cui sopra.
Considera anche la spiegazione di base nella risposta che ho collegato sopra:

  • Sostituisci le stringhe vuote con valori null