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

Indstil tomme strenge ('') til NULL i hele databasen

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


  1. SQL Server Ydeevne TOP CPU Query -2

  2. ORA-12514 fejl efter genstart af serveren

  3. Lower()-funktionen på internationale tegn i postgresql

  4. SQL Server XML-forespørgsel med flere navnerum