PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Como passar OLD, NEW e identificadores para EXECUTE em uma função de trigger?


É assim que sua função de gatilho funcionaria corretamente:
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;

Pontos principais


  • Passe os valores de linha especiais OLD e NEW bem como TG_RELID como valores para EXECUTE com o USING cláusula. Talvez seja necessário transmitir TG_RELID para um tipo de dados adequado. A definição da tabela de tb_modificacoes não é divulgado. Ou você realmente quer outra coisa aqui. Veja abaixo.
    $1 , $2 e $3 na string SQL passada para EXECUTE consulte as expressões no USING cláusula, não para parâmetros de função, que podem ser referenciados com a mesma sintaxe posicional no corpo da função fora EXECUTE .

  • Concatene seu comando SQL dinâmico usando format() . Muito mais limpo e seguro. Cite e escape identificadores , código e valores devidamente! %1$I e %1$L são especificadores de formato para format() . Leia o manual para obter detalhes.

  • Caso correto é necessário! Sua convenção para soletrar identificadores com letras maiúsculas faz sentido no Oracle, onde identificadores sem aspas são convertidos em letras maiúsculas. Não é útil no Postgres, onde tudo é dobrado para letras minúsculas:

  • Não use ILIKE em DAD_NOME ILIKE 'USU_NASCIMENTO' . Os identificadores do Postgres diferenciam maiúsculas de minúsculas. Você poderia tem vários valores correspondentes em dad_nome . Usar = em vez disso e passar identificadores escritos corretamente. E certifique-se de que dad_nome é definido como único. Veja abaixo.

  • Seu comentário diz:MOD_USUARIO , -- Translated to: User (ID) . Mas não é isso que você passa. O manual:

    Você pode querer usar current_user ou session_user em vez de:

  • Você pode remover LIMIT 1 da subconsulta se dad_nome é definido como UNIQUE . Caso contrário, você precisa decidir qual linha escolher em caso de empate - com ORDER BY .

  • As funções de gatilho são necessárias para terminar com um RETURN declaração. Pode ser RETURN NULL para um AFTER acionar. O manual:

Relacionado:

Além: Embora você seja novo no Postgres, talvez queira usar esse tipo de SQL dinâmico avançado com cuidado. Você precisa entender o que está fazendo.