sql >> データベース >  >> RDS >> PostgreSQL

トリガー関数でOLD、NEW、および識別子をEXECUTEに渡す方法は?

    これがトリガー関数が正しく機能する方法です:

    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を慎重に使用することをお勧めします。自分が何をしているのかを理解する必要があります。



    1. mysqlダンプの問題

    2. 国際文字を使用すると、mysqlクエリから二重の結果が得られます。つまり、Å/Ä=A&Ö=O、

    3. Oracle関数の例(戻り値)

    4. Oracleデータベースの文字列列の一定時間インデックス