To powinno wystarczyć:
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;
Bezpośrednią przyczyną komunikatu o błędzie był zewnętrzny SELECT
. Bez celu musisz go zastąpić PERFORM
w plpgsql. Ale wewnętrzny PERFORM
w ciągu zapytania przekazanym do EXECUTE
też się mylił. PERFORM
jest poleceniem plpgsql, niepoprawnym w ciągu SQL przekazanym do EXECUTE
, który oczekuje kodu SQL. Musisz użyć SELECT
tam. Wreszcie OLD
i NEW
nie są widoczne w EXECUTE
i każdy z nich zgłosi swój własny wyjątek tak, jak ty go miałeś. Wszystkie problemy są naprawiane przez upuszczenie PERFORM
.
Prosty i szybki sposób na uzyskanie wartości dynamicznej nazwy kolumny z typów wierszy OLD
i NEW
:rzutuj na json
, możesz sparametryzować nazwę klucza, jak pokazano. Powinna być nieco prostsza i szybsza niż alternatywa z dynamicznym SQL - co również jest możliwe, na przykład:
...
EXECUTE format('SELECT validate_bid_modifiers_count(table_name
, column_name
, ($1.%I)::bigint
, devices_count)', column_name)
USING OLD;
...
Powiązane:
Na bok:Nie wiem, dlaczego potrzebujesz ciężkich zamków.
Na bok 2:Rozważ napisanie osobnej funkcji wyzwalacza dla każdego wyzwalacza. Bardziej hałaśliwe DDL, ale prostsze i szybsze do wykonania.