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

トリガー関数で行タイプの動的列名にアクセスします

    これでうまくいくはずです:

    CREATE OR REPLACE FUNCTION device_bid_modifiers_count_per()
      RETURNS TRIGGER AS
    $func$
    DECLARE
       devices_count int      := device_types_count();
       table_name    regclass := TG_ARGV[0];
       column_name   text     := TG_ARGV[1];
    BEGIN
       LOCK TABLE device_types IN EXCLUSIVE MODE;
       EXECUTE format('LOCK TABLE %s IN EXCLUSIVE MODE', table_name);
    
       IF TG_OP = 'DELETE' THEN
          PERFORM validate_bid_modifiers_count(table_name
                                             , column_name
                                             , (row_to_json(OLD) ->> column_name)::bigint
                                             , devices_count);
       ELSE
          PERFORM validate_bid_modifiers_count(table_name
                                             , column_name
                                             , (row_to_json(NEW) ->> column_name)::bigint
                                             , devices_count);
       END IF;
    
       RETURN NEW;
    END
    $func$  LANGUAGE plpgsql;

    エラーメッセージの直接の原因は、外側のSELECTでした。 。ターゲットがない場合は、PERFORMに置き換える必要があります plpgsqlで。しかし、内側のPERFORM EXECUTEに渡されるクエリ文字列内 も間違っていました。 PERFORM はplpgsqlコマンドであり、EXECUTEに渡されるSQL文字列では無効です。 、SQLコードが必要です。 SELECTを使用する必要があります そこの。最後にOLD およびNEW EXECUTE内には表示されません そして、それぞれがあなたがそれを持っていた方法で彼ら自身の例外を提起するでしょう。 EXECUTEを削除すると、すべての問題が修正されます。 。

    動的な列名の値を取得するための簡単で高速な方法 行タイプからOLD およびNEWjsonにキャスト 、次に、示されているようにキー名をパラメーター化できます。動的SQLを使用する代替手段よりも少し単純で高速である必要があります。これは、次のように可能です。

      ...
      EXECUTE format('SELECT validate_bid_modifiers_count(table_name
                                                        , column_name
                                                        , ($1.%I)::bigint
                                                        , devices_count)', column_name)
      USING OLD;
      ...

    関連:

    余談ですが、なぜ重い錠が必要なのかわかりません。

    余談2:代わりに、トリガーごとに個別のトリガー関数を作成することを検討してください。ノイズの多いDDLですが、実行が簡単で高速です。



    1. SQLAlchemyDateTimeタイムゾーン

    2. PostgreSQLの一意のインデックスと文字列の大文字小文字

    3. データの重複排除時に避けるべき5つのよくある間違い

    4. MySQLデータベース内のすべてのテーブルを一覧表示する4つの方法