sql >> Base de Datos >  >> RDS >> PostgreSQL

¿Cómo pasar identificadores ANTIGUOS, NUEVOS y para EJECUTAR en una función de activación?

Así es como su función de activación funcionaría correctamente:

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;

Puntos principales

  • Pase los valores de fila especiales OLD y NEW así como TG_RELID como valores para EXECUTE con el USING cláusula. Puede que tengas que lanzar TG_RELID a un tipo de datos adecuado. La definición de la tabla de tb_modificacoes no se revela. O realmente quieres algo más aquí. Consulte a continuación.
    $1 , $2 y $3 en la cadena SQL pasada a EXECUTE referirse a expresiones en el USING cláusula, no a los parámetros de la función, a los que se puede hacer referencia con la misma sintaxis posicional en el cuerpo de la función fuera EXECUTE .

  • Concatene su comando SQL dinámico usando format() . Mucho más limpio y seguro. Citar y escapar identificadores , código y valores ¡adecuadamente! %1$I y %1$L son especificadores de formato para format() . Lea el manual para obtener más detalles.

  • ¡Se requiere el caso correcto! Su convención para deletrear identificadores con letras mayúsculas tiene sentido en Oracle, donde los identificadores sin comillas se convierten en letras mayúsculas. No es útil en Postgres, donde todo se pliega en minúsculas:

  • No uses ILIKE en DAD_NOME ILIKE 'USU_NASCIMENTO' . Los identificadores de Postgres distinguen entre mayúsculas y minúsculas. podrías tener múltiples valores coincidentes en dad_nome . Usa = en su lugar y pase los identificadores escritos correctamente. Y asegúrate de que dad_nome se define único. Ver más abajo.

  • Tu comentario dice:MOD_USUARIO , -- Translated to: User (ID) . Pero eso no es lo que pasas. El manual:

    Es posible que desee utilizar current_user o session_user en cambio:

  • Puedes eliminar LIMIT 1 de la subconsulta if dad_nome se define UNIQUE . De lo contrario, debe decidir qué fila elegir en caso de empate, con ORDER BY .

  • Las funciones de activación son requeridas para terminar con un RETURN declaración. También podría ser RETURN NULL para un AFTER generar. El manual:

Relacionado:

Aparte: Si bien es nuevo en Postgres, es posible que desee utilizar este tipo de SQL dinámico avanzado con cuidado. Necesita entender lo que está haciendo.