De meest efficiënte manier om dit te bereiken:
- Voer een enkele
UPDATE
uit per tafel. - Alleen null-kolommen bijwerken (niet gedefinieerd
NOT NULL
) met een daadwerkelijke lege tekenreeks. - Alleen rijen bijwerken met een daadwerkelijke lege tekenreeks.
- Laat andere waarden ongewijzigd.
Dit gerelateerde antwoord heeft een plpgsql-functie die de UPDATE
. bouwt en uitvoert commando met behulp van systeemcatalogus pg_attribute
automatisch en veilig voor een bepaalde tafel:
- Vervang lege tekenreeksen door null-waarden
Gebruik van de functie f_empty2null()
van dit antwoord kun je als volgt door geselecteerde tabellen bladeren:
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$;
Voorzichtig! Hiermee worden alle lege tekenreeksen in alle kolommen van alle gebruikerstabellen in de database bijgewerkt. Zorg ervoor dat u dat wilt, anders kan uw database worden vernietigd.
Je hebt UPDATE
nodig privileges op alle geselecteerde tafels, natuurlijk.
Als kinderbeveiliging heb ik commentaar gegeven op de lading.
Je hebt misschien opgemerkt dat ik de systeemcatalogi rechtstreeks gebruik, niet het informatieschema (wat ook zou werken). Over dit:
- Hoe te controleren of een tabel in een bepaald schema bestaat
- Query om namen van uitvoerkolommen en gegevenstypen van een query, tabel of weergave te retourneren
Voor herhaald gebruik
Hier is een geïntegreerde oplossing voor herhaald gebruik. Zonder veiligheidsvoorzieningen:
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;
Bel:
SELECT * FROM pg_temp.f_all_empty2null();
Retourneren:
_tables | _rows
---------+---------
23 | 123456
Opmerking hoe ik zowel de tabel- als de kolomnamen op de juiste manier heb ontsnapt!
c.oid::regclass AS tbl, quote_ident(attname) AS col
Overweeg:
- Tabelnaam als een PostgreSQL-functieparameter
Voorzichtig! Dezelfde waarschuwing als hierboven.
Beschouw ook de basisuitleg in het antwoord dat ik hierboven heb gelinkt:
- Vervang lege tekenreeksen door null-waarden