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.