É 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 especiaisOLDeNEWbem comoTG_RELIDcomo valores paraEXECUTEcom oUSINGcláusula. Talvez seja necessário transmitirTG_RELIDpara um tipo de dados adequado. A definição da tabela detb_modificacoesnão é divulgado. Ou você realmente quer outra coisa aqui. Veja abaixo.$1,$2e$3na string SQL passada paraEXECUTEconsulte as expressões noUSINGcláusula, não para parâmetros de função, que podem ser referenciados com a mesma sintaxe posicional no corpo da função foraEXECUTE.
-
Concatene seu comando SQL dinâmico usandoformat(). Muito mais limpo e seguro. Cite e escape identificadores , código e valores devidamente!%1$Ie%1$Lsão especificadores de formato paraformat(). 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 useILIKEemDAD_NOME ILIKE 'USU_NASCIMENTO'. Os identificadores do Postgres diferenciam maiúsculas de minúsculas. Você poderia tem vários valores correspondentes emdad_nome. Usar=em vez disso e passar identificadores escritos corretamente. E certifique-se de quedad_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 usarcurrent_userousession_userem vez de:
-
Você pode removerLIMIT 1da subconsulta sedad_nomeé definido comoUNIQUE. Caso contrário, você precisa decidir qual linha escolher em caso de empate - comORDER BY.
-
As funções de gatilho são necessárias para terminar com umRETURNdeclaração. Pode serRETURN NULLpara umAFTERacionar. O manual:
Relacionado:
- Como passar NEW.* para EXECUTE na função trigger
- Substitua aspas duplas por aspas simples no Postgres (plpgsql)
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.