PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Accedi al nome della colonna dinamica del tipo di riga nella funzione di attivazione

Questo dovrebbe farlo:

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;

La causa immediata del messaggio di errore era il SELECT esterno . Senza target, devi sostituirlo con PERFORM in plpgsql. Ma il PERFORM interno nella stringa di query passata a EXECUTE era sbagliato, anche. PERFORM è un comando plpgsql, non valido in una stringa SQL passata a EXECUTE , che prevede codice SQL. Devi usare SELECT là. Infine OLD e NEW non sono visibili all'interno di EXECUTE e ciascuno solleverebbe una propria eccezione come l'hai avuta tu. Tutti i problemi vengono risolti rilasciando EXECUTE .

Un modo semplice e veloce per ottenere il valore di un nome di colonna dinamico dalla riga digita OLD e NEW :trasmetti su json , quindi puoi parametrizzare il nome della chiave come mostrato. Dovrebbe essere un po' più semplice e veloce dell'alternativa con SQL dinamico, il che è anche possibile, come:

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

Correlati:

A parte:non sono sicuro del motivo per cui hai bisogno delle serrature pesanti.

A parte 2:considera invece di scrivere una funzione di trigger separata per ciascun trigger. DDL più rumoroso, ma più semplice e veloce da eseguire.