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

INSERT med dynamisk tabelnavn i triggerfunktion

PostgreSQL 9.1 eller nyere

format() har en indbygget måde at undslippe identifikatorer. Enklere end før:

CREATE OR REPLACE FUNCTION foo_before()
  RETURNS trigger AS
$func$
BEGIN
   EXECUTE format('INSERT INTO %I.%I SELECT $1.*'
                , TG_TABLE_SCHEMA, TG_TABLE_NAME || 'shadow')
   USING OLD;

   RETURN OLD;
END
$func$  LANGUAGE plpgsql;

Fungerer med en VALUES udtryk også.

db<>spil her
Gamle sqlfiddle.

Vigtige punkter

  • Brug format() eller quote_ident() at citere identifikatorer (automatisk og kun hvor det er nødvendigt), og dermed forsvare mod SQL-injektion og simple syntaksovertrædelser.
    Dette er nødvendigt , selv med dine egne tabelnavne!
  • Skema-kvalificere tabelnavnet. Afhængigt af den aktuelle search_path indstilling af et blottet tabelnavn kan ellers løses til en anden tabel med samme navn i et andet skema.
  • Brug EXECUTE for dynamiske DDL-sætninger.
  • Bestå værdier sikkert med USING klausul.
  • Se den fine manual om udførelse af dynamiske kommandoer i plpgsql.
  • Bemærk atRETURN OLD; i triggerfunktionen er påkrævet for en trigger BEFORE DELETE . Detaljer i manualen her.

Du får fejlmeddelelsen i din næsten vellykkede version, fordi OLD er ikke synlig inde i EXECUTE . Og hvis du vil sammenkæde individuelle værdier af den dekomponerede række, som du prøvede, skal du forberede tekstrepræsentationen af ​​hver enkelt kolonne med quote_literal() for at garantere gyldig syntaks. Du skal også vide kolonnenavne på forhånd for at håndtere dem eller forespørge systemkatalogerne - hvilket står imod din idé om at have en simpel, dynamisk triggerfunktion ...

Min løsning undgår alle disse komplikationer. Også forenklet en smule.

PostgreSQL 9.0 eller tidligere

format() er ikke tilgængelig endnu, så:

CREATE OR REPLACE FUNCTION foo_before()
  RETURNS trigger AS
$func$
BEGIN
    EXECUTE 'INSERT INTO ' || quote_ident(TG_TABLE_SCHEMA)
                    || '.' || quote_ident(TG_TABLE_NAME || 'shadow')
                    || ' SELECT $1.*'
    USING OLD;

    RETURN OLD;
END
$func$  LANGUAGE plpgsql;

Relateret:

  • Hvordan bruger man TG_TABLE_NAME dynamisk i PostgreSQL 8.2?


  1. Føj ordensindikatoren til en dato i Oracle

  2. Opret en midlertidig tabel i SQL Server

  3. Sådan angives sorteringen i en forespørgsel i SQL Server (T-SQL)

  4. Databasesikkerhed i Oracle