Dit zou het moeten doen:
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;
De directe oorzaak van de foutmelding was de buitenste SELECT
. Zonder doel moet je het vervangen door PERFORM
in plpgsql. Maar de innerlijke PERFORM
in de queryreeks doorgegeven aan EXECUTE
was ook fout. PERFORM
is een plpgsql-opdracht, niet geldig in een SQL-string die wordt doorgegeven aan EXECUTE
, die SQL-code verwacht. Je moet SELECT
. gebruiken daar. Eindelijk OLD
en NEW
zijn niet zichtbaar in EXECUTE
en zou elk een eigen uitzondering opwerpen zoals jij het had. Alle problemen worden opgelost door EXECUTE
. te verwijderen .
Een eenvoudige en snelle manier om de waarde van een dynamische kolomnaam te verkrijgen uit de rijtypen OLD
en NEW
:casten naar json
, dan kunt u de sleutelnaam parametriseren zoals aangetoond. Zou iets eenvoudiger en sneller moeten zijn dan het alternatief met dynamische SQL - wat ook mogelijk is, zoals:
...
EXECUTE format('SELECT validate_bid_modifiers_count(table_name
, column_name
, ($1.%I)::bigint
, devices_count)', column_name)
USING OLD;
...
Gerelateerd:
Terzijde:ik weet niet zeker waarom je de zware sloten nodig hebt.
Terzijde 2:Overweeg in plaats daarvan een aparte triggerfunctie te schrijven voor elke trigger. Meer luidruchtige DDL, maar eenvoudiger en sneller uit te voeren.