Cela devrait le faire :
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;
La cause immédiate du message d'erreur était le SELECT
externe . Sans cible, vous devez le remplacer par PERFORM
dans plpgsql. Mais le PERFORM
intérieur dans la chaîne de requête passée à EXECUTE
avait tort aussi. PERFORM
est une commande plpgsql, non valide dans une chaîne SQL passée à EXECUTE
, qui attend du code SQL. Vous devez utiliser SELECT
là. Enfin OLD
et NEW
ne sont pas visibles dans EXECUTE
et soulèveraient chacun une exception qui leur était propre, comme vous l'aviez fait. Tous les problèmes sont résolus en supprimant EXECUTE
.
Un moyen simple et rapide d'obtenir la valeur d'un nom de colonne dynamique à partir des types de lignes OLD
et NEW
:cast en json
, vous pouvez alors paramétrer le nom de la clé comme démontré. Devrait être un peu plus simple et plus rapide que l'alternative avec SQL dynamique - ce qui est également possible, comme :
...
EXECUTE format('SELECT validate_bid_modifiers_count(table_name
, column_name
, ($1.%I)::bigint
, devices_count)', column_name)
USING OLD;
...
Connexe :
- Obtenir des valeurs à partir de différentes colonnes dans un déclencheur générique
- Déclencheur avec nom de champ dynamique
A part:Je ne sais pas pourquoi vous avez besoin des serrures lourdes.
Aside 2:Envisagez plutôt d'écrire une fonction de déclenchement distincte pour chaque déclencheur. DDL plus bruyant, mais plus simple et plus rapide à exécuter.