4

カウントによって巨大なテーブルを新しいテーブルにロールアップしています。ここで、すべての空の文字列をに変更し、NULLいくつかの列も型キャストします。いくつかの投稿を読みましたが、クエリが見つかりませんでした。これにより、複数のステートメントを使用せずに、1つのクエリですべての列にまたがって実行できます。

すべての列を反復処理して、セルをnullの空の文字列に置き換えることが可能かどうかを教えてください。

参照:SQL Serverを使用して空のスペースをnull値に変換する方法は?

4

1 に答える 1

5

私の知る限り、テーブルのすべての列で空の文字列を置き換える組み込み関数はありません。それを処理するためにplpgsql 関数を書くことができます。

次の関数は、指定されたテーブルのすべての基本的な文字型列の空の文字列を に置き換えますNULLintegerその後、残りの文字列が有効な数値リテラルである場合にキャストできます。

CREATE OR REPLACE FUNCTION f_empty_text_to_null(_tbl regclass, OUT updated_rows int)
  LANGUAGE plpgsql AS
$func$
DECLARE
   _typ  CONSTANT regtype[] := '{text, bpchar, varchar}';  -- ARRAY of all basic character types
   _sql  text;
BEGIN
   SELECT INTO _sql                       -- build SQL command
          'UPDATE ' || _tbl
          || E'\nSET    ' || string_agg(format('%1$s = NULLIF(%1$s, '''')', col), E'\n      ,')
          || E'\nWHERE  ' || string_agg(col || ' = ''''', ' OR ')
   FROM  (
      SELECT quote_ident(attname) AS col
      FROM   pg_attribute
      WHERE  attrelid = _tbl              -- valid, visible, legal table name 
      AND    attnum >= 1                  -- exclude tableoid & friends
      AND    NOT attisdropped             -- exclude dropped columns
      AND    NOT attnotnull               -- exclude columns defined NOT NULL!
      AND    atttypid = ANY(_typ)         -- only character types
      ORDER  BY attnum
      ) sub;

   -- RAISE NOTICE '%', _sql;  -- test?

   -- Execute
   IF _sql IS NULL THEN
      updated_rows := 0;                        -- nothing to update
   ELSE
      EXECUTE _sql;
      GET DIAGNOSTICS updated_rows = ROW_COUNT; -- Report number of affected rows
   END IF;
END
$func$;

電話:

SELECT f_empty2null('mytable');
SELECT f_empty2null('myschema.mytable');

列名も取得するにはupdated_rows:

SELECT * FROM f_empty2null('mytable');

ここでdb<>fiddle
古いsqlfiddle

主なポイント

  • テーブル名は有効で表示可能である必要があり、呼び出し元のユーザーは必要なすべての権限を持っている必要があります。これらの条件のいずれかが満たされない場合、関数は何もしません。つまり、何も破棄できません。それを確認するために、オブジェクト識別子の型regclassにキャストします。
    テーブル名はそのまま ( 'mytable') で指定でき、その後 がsearch_path決定します。または、特定のスキーマを選択するスキーマ修飾 ( 'myschema.mytable')。

  • システム カタログを照会して、テーブルのすべての ( character-type ) 列を取得します。提供された関数は、次の基本的な文字タイプを使用します: text, bpchar, varchar, "char". 関連する列のみが処理されます。

  • quote_ident()またはを使用format()して列名をサニタイズし、SQLi から保護します

  • 更新されたバージョンでは、基本的な SQL 集計関数を使用して、string_agg()ループなしでコマンド文字列を構築します。これは、よりシンプルで高速です。そしてよりエレガントに。:)

  • で動的 SQLEXECUTEを使用する必要があります。

  • 更新されたバージョンでは、定義された列が除外され、単一のステートメントNOT NULLで各行が 1 回だけ更新されます。

  • 最新バージョンの PostgreSQL で動作するはずです。Postgres 9.1、9.3、9.5、および 13 でテスト済み。

于 2012-05-21T13:47:49.253 に答える