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