これを達成するための最も効率的な方法:
- 単一の
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値に置き換えます