Dette burde gøre det:
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;
Den umiddelbare årsag til fejlmeddelelsen var den ydre SELECT
. Uden mål skal du erstatte det med PERFORM
i plpgsql. Men den indre PERFORM
i forespørgselsstrengen sendt til EXECUTE
var også forkert. PERFORM
er en plpgsql-kommando, ikke gyldig i en SQL-streng sendt til EXECUTE
, som forventer SQL-kode. Du skal bruge SELECT
der. Endelig OLD
og NEW
er ikke synlige i EXECUTE
og ville hver især rejse sin egen undtagelse, som du havde det. Alle problemer løses ved at droppe EXECUTE
.
En enkel og hurtig måde at få værdien af et dynamisk kolonnenavn fra rækketyperne OLD
og NEW
:cast til json
, så kan du parametrere nøglenavnet som vist. Bør være en smule enklere og hurtigere end alternativet med dynamisk SQL - hvilket også er muligt, som:
...
EXECUTE format('SELECT validate_bid_modifiers_count(table_name
, column_name
, ($1.%I)::bigint
, devices_count)', column_name)
USING OLD;
...
Relateret:
Til side:Ikke sikker på, hvorfor du har brug for de tunge låse.
Bortset fra 2:Overvej at skrive en separat triggerfunktion for hver trigger i stedet. Mere støjende DDL, men enklere og hurtigere at udføre.