Mělo by to stačit:
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;
Bezprostřední příčinou chybové zprávy byl vnější SELECT
. Bez cíle jej musíte nahradit výrazem PERFORM
v plpgsql. Ale vnitřní PERFORM
v řetězci dotazu předaném EXECUTE
se také mýlil. PERFORM
je příkaz plpgsql, který není platný v řetězci SQL předávaném EXECUTE
, který očekává kód SQL. Musíte použít SELECT
tam. Konečně OLD
a NEW
nejsou viditelné uvnitř EXECUTE
a každý by vyvolal svou vlastní výjimku, jak jste to měli vy. Všechny problémy jsou vyřešeny zrušením EXECUTE
.
Jednoduchý a rychlý způsob, jak získat hodnotu názvu dynamického sloupce z typů řádků OLD
a NEW
:přenést do json
, pak můžete parametrizovat název klíče, jak je ukázáno. Mělo by to být o něco jednodušší a rychlejší než alternativa s dynamickým SQL – což je také možné, jako:
...
EXECUTE format('SELECT validate_bid_modifiers_count(table_name
, column_name
, ($1.%I)::bigint
, devices_count)', column_name)
USING OLD;
...
Související:
Stranou:Nejste si jisti, proč potřebujete těžké zámky.
Vedle 2:Zvažte místo toho napsat samostatnou funkci spouštění pro každý spouštěč. Hlučnější DDL, ale jednodušší a rychlejší na provedení.