Nejúčinnější způsob, jak toho dosáhnout:
- Spusťte jeden příkaz
UPDATE
na stůl. - Aktualizovat pouze sloupce s povolenou hodnotou Null (nedefinováno
NOT NULL
) s jakýmkoli skutečným prázdným řetězcem. - Aktualizujte řádky pouze se skutečným prázdným řetězcem.
- Ponechte ostatní hodnoty beze změny.
Tato související odpověď má funkci plpgsql, která vytváří a spouští UPDATE
příkaz pomocí systémového katalogu pg_attribute
automaticky a bezpečně pro jakoukoli danou tabulku:
- Nahraďte prázdné řetězce hodnotami null
Pomocí funkce f_empty2null()
z této odpovědi můžete procházet vybrané tabulky takto:
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$;
Pozor! Tím se aktualizují všechny prázdné řetězce ve všech sloupcích všech uživatelských tabulek v DB. Ujistěte se, že to je to, co chcete, jinak by to mohlo zničit vaši databázi.
Potřebujete UPDATE
oprávnění na všech vybraných tabulkách, samozřejmě.
Jako dětská pojistka jsem komentoval užitečné zatížení.
Možná jste si všimli, že používám přímo systémové katalogy, nikoli informační schéma (což by také fungovalo). O tomto:
- Jak zkontrolovat, zda tabulka v daném schématu existuje
- Dotaz pro vrácení názvů výstupních sloupců a datových typů dotazu, tabulky nebo zobrazení
Pro opakované použití
Zde je integrované řešení pro opakované použití. Bez bezpečnostních zařízení:
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;
Volejte:
SELECT * FROM pg_temp.f_all_empty2null();
Vrátí:
_tables | _rows
---------+---------
23 | 123456
Poznámka jak jsem správně escapoval názvy tabulek i sloupců!
c.oid::regclass AS tbl, quote_ident(attname) AS col
Zvažte:
- Název tabulky jako parametr funkce PostgreSQL
Pozor! Stejné varování jako výše.
Zvažte také základní vysvětlení v odpovědi, kterou jsem uvedl výše:
- Nahraďte prázdné řetězce hodnotami null