PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Greifen Sie in der Triggerfunktion auf den dynamischen Spaltennamen des Zeilentyps zu

Das sollte es tun:

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;

Die unmittelbare Ursache für die Fehlermeldung war das äußere SELECT . Ohne Ziel müssen Sie es durch PERFORM ersetzen in plpgsql. Aber das innere PERFORM in der an EXECUTE übergebenen Abfragezeichenfolge war auch falsch. PERFORM ist ein plpgsql-Befehl, nicht gültig in einer SQL-Zeichenfolge, die an EXECUTE übergeben wird , die SQL-Code erwartet. Sie müssen SELECT verwenden dort. Schließlich OLD und NEW sind innerhalb von EXECUTE nicht sichtbar und würde jeder eine eigene Ausnahme auslösen, so wie Sie es hatten. Alle Probleme werden durch Ablegen von EXECUTE behoben .

Eine einfache und schnelle Möglichkeit, den Wert eines dynamischen Spaltennamens abzurufen aus den Zeilentypen OLD und NEW :in json umwandeln , dann können Sie den Schlüsselnamen wie gezeigt parametrisieren. Sollte etwas einfacher und schneller sein als die Alternative mit dynamischem SQL - was auch möglich ist, wie:

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

Verwandte:

Beiseite:Ich bin mir nicht sicher, warum Sie die schweren Schlösser brauchen.

Nebenbemerkung 2:Erwägen Sie stattdessen, für jeden Trigger eine separate Triggerfunktion zu schreiben. Lauteres DDL, aber einfacher und schneller auszuführen.