すべてのテーブルに関数を記述したり、クライアント側でそれを実行したりすることなく、すべてのテキストデータを強制的に大文字にする方法はありますか?
正しい値を強制するは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でテスト済み。
関連: