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

Comment passer OLD, NEW et les identifiants à EXECUTE dans une fonction trigger ?

Voici comment votre fonction de déclenchement fonctionnerait correctement :

CREATE OR REPLACE FUNCTION loca_app.func_historico_mod_usuarios()
  RETURNS trigger AS
$func$
BEGIN
   EXECUTE format(
      'INSERT INTO loca_app.tb_modificacoes
              (mod_momento, mod_valor_anterior, mod_valor_atual, mod_usuario, mod_dado)
       VALUES (now()      , $1.%1$I           , $2.%1$I        , $3         , $4)

              )', TG_ARGV[0])
   USING OLD, NEW, TG_RELID
      , (SELECT dad_id FROM loca_app.tb_dados
         WHERE  dad_nome = TG_ARGV[0]  -- cast? see blow
         LIMIT  1);

   RETURN NULL;  -- only good for AFTER trigger
END
$func$ LANGUAGE plpgsql;

Points majeurs

  • Passez les valeurs de ligne spéciales OLD et NEW ainsi que TG_RELID en tant que valeurs pour EXECUTE avec le USING clause. Vous devrez peut-être caster TG_RELID à un type de données approprié. La définition de table de tb_modificacoes n'est pas divulgué. Ou vous voulez vraiment quelque chose d'autre ici. Voir ci-dessous.
    $1 , $2 et $3 dans la chaîne SQL passée à EXECUTE faire référence aux expressions dans le USING clause, pas aux paramètres de fonction, qui peuvent être référencés avec la même syntaxe positionnelle dans le corps de la fonction outside EXECUTE .

  • Concaténez votre commande SQL dynamique en utilisant format() . Beaucoup plus propre et plus sûr. Citez et échappez les identifiants , code et valeurs correctement! %1$I et %1$L sont des spécificateurs de format pour format() . Lire le manuel pour plus de détails.

  • La casse correcte est requise ! Votre convention d'orthographe des identifiants avec des lettres majuscules est logique dans Oracle, où les identifiants sans guillemets sont convertis en lettres majuscules. Ce n'est pas utile dans Postgres, où tout est plié en minuscules :

  • N'utilisez pas ILIKE dans DAD_NOME ILIKE 'USU_NASCIMENTO' . Les identifiants Postgres sont sensibles à la casse. Vous pourriez avoir plusieurs valeurs correspondantes dans dad_nome . Utilisez = à la place et transmettez les identifiants correctement orthographiés. Et assurez-vous que dad_nome est défini unique. Voir ci-dessous.

  • Votre commentaire dit :MOD_USUARIO , -- Translated to: User (ID) . Mais ce n'est pas ce que vous passez. Le manuel :

    Vous pouvez utiliser current_user ou session_user à la place :

  • Vous pouvez supprimer LIMIT 1 de la sous-requête si dad_nome est défini UNIQUE . Sinon, vous devez décider quelle ligne choisir en cas d'égalité - avec ORDER BY .

  • Les fonctions de déclenchement sont obligatoires se terminer par un RETURN déclaration. Pourrait tout aussi bien être RETURN NULL pour un AFTER gâchette. Le manuel :

Connexe :

À part : Pendant que vous êtes nouveau sur Postgres, vous voudrez peut-être utiliser ce type de SQL dynamique avancé avec précaution. Vous devez comprendre ce que vous faites.