PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Come passare VECCHIO, NUOVO e identificatori per ESEGUIRE in una funzione di attivazione?

Ecco come funzionerebbe correttamente la tua funzione di attivazione:

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;

Punti principali

  • Passa i valori di riga speciali OLD e NEW così come TG_RELID come valori a EXECUTE con il USING clausola. Potrebbe essere necessario trasmettere TG_RELID a un tipo di dati di adattamento. La definizione della tabella di tb_modificacoes è sconosciuto. O vuoi davvero qualcos'altro qui. Vedi sotto.
    $1 , $2 e $3 nella stringa SQL passata a EXECUTE fare riferimento alle espressioni in USING clausola, non ai parametri della funzione, a cui è possibile fare riferimento con la stessa sintassi posizionale nel corpo della funzione esterno EXECUTE .

  • Concatena il tuo comando SQL dinamico usando format() . Molto più pulito e sicuro. Cita ed esci da identificatori , codice e valori propriamente! %1$I e %1$L sono identificatori di formato per format() . Leggi il manuale per i dettagli.

  • È necessario il caso corretto! La tua convenzione per scrivere gli identificatori con lettere maiuscole ha senso in Oracle, dove gli identificatori senza virgolette vengono convertiti in lettere maiuscole. Non è utile in Postgres, dove invece tutto è piegato in minuscolo:

  • Non utilizzare ILIKE in DAD_NOME ILIKE 'USU_NASCIMENTO' . Gli identificatori Postgres fanno distinzione tra maiuscole e minuscole. Potresti hanno più valori corrispondenti in dad_nome . Usa = invece e passare gli identificatori scritti correttamente. E assicurati dad_nome è definito unico. Vedi sotto.

  • Il tuo commento dice:MOD_USUARIO , -- Translated to: User (ID) . Ma non è quello che passi. Il manuale:

    Potresti voler usare current_user o session_user invece:

  • Puoi rimuovere LIMIT 1 dalla sottoquery se dad_nome è definito UNIQUE . Altrimenti devi decidere quale riga scegliere in caso di parità - con ORDER BY .

  • Le funzioni di attivazione sono richieste per terminare con un RETURN dichiarazione. Potrebbe anche essere RETURN NULL per un AFTER grilletto. Il manuale:

Correlati:

A parte: Anche se sei un nuovo utente di Postgres, potresti voler utilizzare con attenzione questo tipo di SQL dinamico avanzato. Devi capire cosa stai facendo.