PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Wie werden OLD, NEW und Bezeichner in einer Triggerfunktion an EXECUTE übergeben?

So würde Ihre Trigger-Funktion richtig funktionieren:

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;

Wichtige Punkte

  • Übergeben Sie die speziellen Zeilenwerte OLD und NEW sowie TG_RELID als Werte zu EXECUTE mit dem USING Klausel. Möglicherweise müssen Sie TG_RELID wirken zu einem passenden Datentyp. Die Tabellendefinition von tb_modificacoes ist nicht bekannt. Oder Sie wollen wirklich etwas anderes hier. Siehe unten.
    $1 , $2 und $3 in der an EXECUTE übergebenen SQL-Zeichenfolge beziehen sich auf Ausdrücke in USING Klausel, nicht zu Funktionsparametern, die mit der gleichen Positionssyntax im Funktionskörper außen referenziert werden können EXECUTE .

  • Verketten Sie Ihren dynamischen SQL-Befehl mit format() . Viel sauberer und sicherer. Bezeichner in Anführungszeichen setzen und mit Escapezeichen versehen , Code und Werte richtig! %1$I und %1$L sind Formatbezeichner für format() . Lesen Sie das Handbuch für Details.

  • Korrekte Groß-/Kleinschreibung erforderlich! Ihre Konvention, Bezeichner mit Großbuchstaben zu schreiben, ist in Oracle sinnvoll, wo Bezeichner ohne Anführungszeichen in Großbuchstaben umgewandelt werden. Es ist in Postgres nicht nützlich, wo stattdessen alles in Kleinbuchstaben gefaltet wird:

  • Verwenden Sie nicht ILIKE in DAD_NOME ILIKE 'USU_NASCIMENTO' . Bei Postgres-Bezeichnern wird zwischen Groß- und Kleinschreibung unterschieden. Sie könnten haben mehrere übereinstimmende Werte in dad_nome . Verwenden Sie = stattdessen und richtig geschriebene Bezeichner übergeben. Und stellen Sie sicher, dass dad_nome eindeutig definiert ist. Siehe unten.

  • Ihr Kommentar lautet:MOD_USUARIO , -- Translated to: User (ID) . Aber das ist nicht, was Sie passieren. Das Handbuch:

    Sie können current_user verwenden oder session_user stattdessen:

  • Sie können LIMIT 1 entfernen aus der Unterabfrage if dad_nome ist UNIQUE definiert . Andernfalls müssen Sie entscheiden, welche Reihe Sie im Falle eines Gleichstands auswählen möchten - mit ORDER BY .

  • Triggerfunktionen sind erforderlich mit einem RETURN abzuschließen Aussage. Könnte genauso gut RETURN NULL sein für ein AFTER Abzug. Das Handbuch:

Verwandte:

Nebenbei: Auch wenn Sie neu bei Postgres sind, sollten Sie diese Art von erweitertem dynamischem SQL vorsichtig verwenden. Sie müssen verstehen, was Sie tun.