PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Accéder au nom de colonne dynamique du type de ligne dans la fonction de déclenchement

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 :

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.