sql >> データベース >  >> RDS >> PostgreSQL

データベース全体で空の文字列('')をNULLに設定します

    これを達成するための最も効率的な方法:

    • 単一のUPDATEを実行します テーブルごと。
    • null許容列のみを更新します(定義されていませんNOT NULL )実際の空の文字列を使用します。
    • 実際の空の文字列でのみ行を更新します。
    • 他の値は変更しないでください。

    この関連する回答には、UPDATEをビルドして実行するplpgsql関数があります。 システムカタログpg_attributeを使用したコマンド 任意のテーブルに対して自動的かつ安全に:

    • 空の文字列をnull値に置き換えます

    関数f_empty2null()を使用する この回答から、次のように選択したテーブルをループできます:

    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$;
    

    注意! これにより、DB内のすべてのユーザーテーブルのすべての列にあるすべての空の文字列が更新されます。それがあなたの望むものであることを確認してください。そうしないと、データベースが破壊される可能性があります。

    UPDATEが必要です もちろん、選択したすべてのテーブルに対する特権。

    子供の安全装置として、私はペイロードにコメントしました。

    情報スキーマではなく、システムカタログを直接使用していることにお気づきかもしれません(これも機能します)。これについて:

    • 特定のスキーマにテーブルが存在するかどうかを確認する方法
    • クエリ、テーブル、またはビューの出力列名とデータ型を返すクエリ

    繰り返し使用する場合

    これは、繰り返し使用するための統合ソリューションです。安全装置なし:

    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;
    

    電話:

    SELECT * FROM pg_temp.f_all_empty2null();
    

    返品:

     _tables | _rows
    ---------+---------
     23      | 123456
    

    テーブル名と列名の両方を適切にエスケープする方法!

    c.oid::regclass AS tbl, quote_ident(attname)  AS col
    

    検討してください:

    • PostgreSQL関数パラメータとしてのテーブル名

    注意! 上記と同じ警告。
    上記でリンクした回答の基本的な説明も考慮してください:

    • 空の文字列をnull値に置き換えます


    1. 16進数をvarchar(datetime)にキャストする方法は?

    2. 遅いクエリでPostgreSQLのパフォーマンスの問題を特定する方法

    3. オラクルで大文字と小文字が区別される理由

    4. SQLServerで一重引用符をエスケープする