Den mest effektive måde at opnå dette på:
- Kør en enkelt
UPDATE
pr. bord. - Opdater kun nullbare kolonner (ikke defineret
NOT NULL
) med enhver faktisk tom streng. - Opdater kun rækker med en faktisk tom streng.
- Lad andre værdier være uændrede.
Dette relaterede svar har en plpgsql-funktion, der bygger og kører UPDATE
kommando ved hjælp af systemkataloget pg_attribute
automatisk og sikkert for enhver given tabel:
- Erstat tomme strenge med null-værdier
Brug af funktionen f_empty2null()
fra dette svar kan du gå gennem udvalgte tabeller som denne:
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$;
Forsigtig! Dette opdaterer alle tomme strenge i alle kolonner i alle brugertabeller i DB. Vær sikker på, at det er det, du vil have, ellers kan det ødelægge din database.
Du skal bruge UPDATE
privilegier på alle udvalgte borde, selvfølgelig.
Som en børnesikkerhedsanordning kommenterede jeg nyttelasten.
Du har måske bemærket, at jeg bruger systemkatalogerne direkte, ikke informationsskemaet (som også ville fungere). Om dette:
- Sådan kontrollerer du, om en tabel findes i et givet skema
- Forespørgsel for at returnere outputkolonnenavne og datatyper for en forespørgsel, tabel eller visning
Til gentagen brug
Her er en integreret løsning til gentagen brug. Uden sikkerhedsanordninger:
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;
Ring til:
SELECT * FROM pg_temp.f_all_empty2null();
Returnerer:
_tables | _rows
---------+---------
23 | 123456
Bemærk hvordan jeg undslap både tabel- og kolonnenavne korrekt!
c.oid::regclass AS tbl, quote_ident(attname) AS col
Overvej:
- Tabelnavn som en PostgreSQL-funktionsparameter
Forsigtig! Samme advarsel som ovenfor.
Overvej også den grundlæggende forklaring i svaret, jeg linkede ovenfor:
- Erstat tomme strenge med null-værdier