これがトリガー関数が正しく機能する方法です:
CREATE OR REPLACE FUNCTION loca_app.func_historico_mod_usuarios()
RETURNS trigger AS
$func$
BEGIN
EXECUTE format(
'INSERT INTO loca_app.tb_modificacoes
(mod_momento, mod_valor_anterior, mod_valor_atual, mod_usuario, mod_dado)
VALUES (now() , $1.%1$I , $2.%1$I , $3 , $4)
)', TG_ARGV[0])
USING OLD, NEW, TG_RELID
, (SELECT dad_id FROM loca_app.tb_dados
WHERE dad_nome = TG_ARGV[0] -- cast? see blow
LIMIT 1);
RETURN NULL; -- only good for AFTER trigger
END
$func$ LANGUAGE plpgsql;
主なポイント
-
特別な行の値を渡す
OLD
およびNEW
TG_RELID
も同様です 値としてEXECUTE
へUSING
で 句。TG_RELID
をキャストする必要があるかもしれません フィッティングデータ型に。tb_modificacoes
のテーブル定義 未公開です。または、ここで何か他のものが本当に必要です。以下を参照してください。$ 1
、$ 2
および$3
EXECUTE
に渡されるSQL文字列内USING
の式を参照してください 条項、ではない 関数パラメータへ。これは、関数本体の外部で同じ位置構文で参照できます。EXECUTE
。 -
format()
。はるかにクリーンで安全です。 識別子を引用してエスケープする 、コード および値 ちゃんと!%1 $ I
および%1 $ L
format()
のフォーマット指定子です 。 詳細については、マニュアルをお読みください。 -
正しいケースが必要です!識別子を大文字で綴る規則は、引用符で囲まれていない識別子が大文字に変換されるOracleでは意味があります。代わりにすべてが小文字に折りたたまれているPostgresでは役に立ちません:
-
ILIKE
は使用しないでくださいDAD_NOME ILIKE'USU_NASCIMENTO'
で 。 Postgres識別子では大文字と小文字が区別されます。あなたはできたdad_nome
に複数の一致する値があります 。=
を使用する 代わりに、正しいスペルの識別子を渡します。そして、dad_nome
を確認してください 一意に定義されます。以下を参照してください。 -
あなたのコメントは言う:
MOD_USUARIO、-翻訳:ユーザー(ID)
。しかし、それはあなたが渡すものではありません。マニュアル:current_user
を使用することをお勧めします またはsession_user
代わりに: -
LIMIT 1
を削除できますdad_nome
の場合はサブクエリからUNIQUE
が定義されています 。それ以外の場合は、同点の場合に選択する行を決定する必要があります-ORDER BY
。 -
トリガー関数は必須です
RETURN
で終了します 声明。RETURN NULL
の場合もありますAFTER
の場合 引き金。 マニュアル:
関連:
脇: Postgresを初めて使用する場合は、この種の高度な動的SQLを慎重に使用することをお勧めします。自分が何をしているのかを理解する必要があります。