Това трябва да го направи:
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;
Непосредствената причина за съобщението за грешка беше външният SELECT
. Без target, трябва да го замените с PERFORM
в plpgsql. Но вътрешният PERFORM
в низа на заявката, предаван на EXECUTE
също беше грешен. PERFORM
е plpgsql команда, не е валидна в SQL низ, предаден на EXECUTE
, който очаква SQL код. Трябва да използвате SELECT
там. Най-накрая OLD
и NEW
не се виждат в EXECUTE
и всеки би издигнал свое собствено изключение, както го направихте вие. Всички проблеми се коригират чрез премахване на EXECUTE
.
Лесен и бърз начин да получите стойността на име на динамична колона от типовете редове OLD
и NEW
:прехвърляне към json
, тогава можете да параметризирате името на ключа, както е показано. Трябва да е малко по-просто и по-бързо от алтернативата с динамичен SQL - което също е възможно, като:
...
EXECUTE format('SELECT validate_bid_modifiers_count(table_name
, column_name
, ($1.%I)::bigint
, devices_count)', column_name)
USING OLD;
...
Свързани:
Настрана:Не съм сигурен защо ви трябват тежките ключалки.
Освен 2:Помислете вместо това да напишете отделна тригерна функция за всеки тригер. По-шумен DDL, но по-прост и по-бърз за изпълнение.