Detta borde göra 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 omedelbara orsaken till felmeddelandet var den yttre SELECT
. Utan mål måste du ersätta det med PERFORM
i plpgsql. Men den inre PERFORM
i frågesträngen som skickades till EXECUTE
var fel också. PERFORM
är ett plpgsql-kommando, inte giltigt i en SQL-sträng som skickas till EXECUTE
, som förväntar sig SQL-kod. Du måste använda SELECT
där. Äntligen OLD
och NEW
är inte synliga i EXECUTE
och skulle var och en ta upp ett eget undantag som du hade det. Alla problem åtgärdas genom att släppa EXECUTE
.
Ett enkelt och snabbt sätt att få värdet av ett dynamiskt kolumnnamn från radtyperna OLD
och NEW
:casta till json
, då kan du parametrisera nyckelnamnet som visas. Borde vara lite enklare och snabbare än alternativet med dynamisk SQL - vilket också är möjligt, som:
...
EXECUTE format('SELECT validate_bid_modifiers_count(table_name
, column_name
, ($1.%I)::bigint
, devices_count)', column_name)
USING OLD;
...
Relaterat:
Bortsett från:Inte säker på varför du behöver de tunga låsen.
Bortsett från 2:Överväg att skriva en separat triggerfunktion för varje trigger istället. Mer bullrig DDL, men enklare och snabbare att köra.