web-dev-qa-db-ja.com

PostgreSQLはすべてのデータに対して大文字を強制します

すべてのテーブルに関数を記述したり、クライアント側でそれを実行したりすることなく、すべてのテキストデータを強制的に大文字にする方法はありますか?

3

正しい値を強制する1つものです。単純なCHECK制約列ごとは確実にジョブを実行できます。

CREATE TABLE foo
   foo_id serial PRIMARY KEY
 , text_column text CHECK (upper(text_column) = text_column)
 , ...
);

すべての入力の自動修正は別のことであり、それほど単純ではありません。ただし、システムカタログで列名とデータ型を検索し、すべての文字データを大文字に変換する汎用トリガー関数を使用して実行できます。安全性は十分ですが、速度が速く、防弾性能が劣ります。複雑なトリガーは、他のトリガーによって簡単に回避または打ち消されるためです。

One汎用トリガー関数for all:

CREATE OR REPLACE FUNCTION trg_all_upper()
  RETURNS trigger AS
$BODY$
DECLARE
   -- basic character types. possibly add citext, domains or custom types
   _typ   CONSTANT regtype[] := '{text, bpchar, varchar, \"char\"}';
   _sql   text;
   _found bool;
BEGIN
   SELECT INTO _sql, _found
          'SELECT ' || string_agg(
              CASE WHEN a.atttypid = ANY(_typ)
              THEN format ('upper(%1$s)::%2$s AS %1$s'
                         , a.col, a.atttypid::regtype)
              ELSE col END
            , ', ') || ' FROM (SELECT ($1).*) t'
        , bool_or(a.atttypid = ANY(_typ))
   FROM  (
      SELECT a.atttypid, quote_ident(attname) AS col
      FROM   pg_attribute a
      WHERE  a.attrelid = TG_RELID  -- object ID of table that fired trigger 
      AND    a.attnum >= 1          -- exclude tableoid & friends
      AND    NOT a.attisdropped     -- exclude dropped columns
      ORDER  BY a.attnum
      ) a;

   -- RAISE NOTICE '%', _sql;
   IF _found THEN
      EXECUTE _sql USING NEW INTO NEW;
   END IF;

   RETURN NEW;
END
$func$  LANGUAGE plpgsql VOLATILE;

トリガーテーブルごと

CREATE TRIGGER all_upper_bef_insupd
BEFORE INSERT OR UPDATE ON big
FOR EACH ROW EXECUTE PROCEDURE trg_all_upper();

_typで定義されている文字データ型の列のall値を大文字に変換します。
Postgres 9.4でテスト済み。

関連:

13