sql >> Database >  >> RDS >> PostgreSQL

Hoe OUDE, NIEUWE en identifiers doorgeven aan EXECUTE in een triggerfunctie?

Dit is hoe uw triggerfunctie correct zou werken:

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;

Belangrijkste punten

  • Geef de speciale rijwaarden door OLD en NEW evenals TG_RELID als waarden om EXECUTE met de USING clausule. Mogelijk moet je TG_RELID casten naar een passend gegevenstype. De tabeldefinitie van tb_modificacoes is niet bekendgemaakt. Of je wilt hier echt iets anders. Zie hieronder.
    $1 , $2 en $3 in de SQL-string doorgegeven aan EXECUTE verwijzen naar uitdrukkingen in de USING clausule, niet naar functieparameters, waarnaar kan worden verwezen met dezelfde positionele syntaxis in de functietekst buiten EXECUTE .

  • Voeg uw dynamische SQL-opdracht samen met format() . Veel schoner en veiliger. Citeer en ontsnap aan ID's , code en waarden naar behoren! %1$I en %1$L zijn formaatspecificaties voor format() . Lees de handleiding voor details.

  • Juiste zaak is vereist! Uw conventie om identifiers met hoofdletters te spellen is logisch in Oracle, waar niet-geciteerde identifiers worden geconverteerd naar hoofdletters. Het is niet handig in Postgres, waar alles in plaats daarvan in kleine letters wordt gevouwen:

  • Gebruik ILIKE niet in DAD_NOME ILIKE 'USU_NASCIMENTO' . Postgres-ID's zijn hoofdlettergevoelig. Je zou meerdere overeenkomende waarden hebben in dad_nome . Gebruik = in plaats daarvan en geef identifiers correct gespeld door. En zorg ervoor dat dad_nome is uniek gedefinieerd. Zie hieronder.

  • Uw commentaar zegt:MOD_USUARIO , -- Translated to: User (ID) . Maar dat is niet wat je passeert. De handleiding:

    Misschien wilt u current_user . gebruiken of session_user in plaats daarvan:

  • Je kunt LIMIT 1 verwijderen uit de subquery als dad_nome is gedefinieerd UNIQUE . Anders moet je beslissen welke rij je kiest in het geval van een gelijkspel - met ORDER BY .

  • Triggerfuncties zijn vereist om te beëindigen met een RETURN uitspraak. Kan net zo goed RETURN NULL zijn voor een AFTER trekker. De handleiding:

Gerelateerd:

Terzijde: Hoewel Postgres nieuw voor u is, wilt u dit soort geavanceerde dynamische SQL misschien zorgvuldig gebruiken. Je moet begrijpen wat je doet.



  1. Oracle 11g:draai meerdere kolommen ongedaan maken en kolomnaam opnemen

  2. 3 manieren om ALL in SQL Server te gebruiken

  3. oracle systimestamp (sysdate) naar milliseconden

  4. Kan geen verbinding maken met RDS-instantie vanuit EC2-instantie