sql >> Databasteknik >  >> RDS >> PostgreSQL

Hur sparar man en data med varierande kommatecken som passerar genom en trigger?

Du kan använda format() för att göra det mycket enklare att skapa en dynamisk SQL-fråga eftersom den automatiskt kommer att hantera identifierare och bokstaver på rätt sätt. En sak som folk vanligtvis förbiser är att du kan utöka ett enda postuttryck till alla dess kolumner med (...).* - detta fungerar även för NEW och OLD registrera variabler i en trigger, t.ex. select (new).*

Du kan också skicka variabler till en dynamisk SQL med using nyckelordet för execute påstående. Det finns ingen anledning att konvertera posten fram och tillbaka mellan en post och en textrepresentation.

Genom att använda den möjligheten kan din triggerfunktion förenklas till:

DECLARE 
  l_sql text;
BEGIN
    IF TG_TABLE_SCHEMA = 'public' THEN
      newtable := TG_TABLE_NAME || '_actividad';
    ELSE
      newtable := TG_TABLE_SCHEMA || '_' || TG_TABLE_NAME || '_actividad';
    END IF;

    PERFORM creartablaactividad(TG_TABLE_SCHEMA, TG_TABLE_NAME);
    l_sql := 'INSERT INTO actividad.%I  SELECT current_user, current_timestamp, %L, ($1).*';

    IF TG_OP = 'DELETE' THEN
      execute format(l_sql, newtable, 'D') using OLD;
      RETURN OLD;
    ELSE
      -- covers UPDATE and INSERT
      execute format(l_sql, newtable, 'U') using NEW;
      RETURN NEW;
    END IF;

    RETURN NULL; -- result is ignored since this is an AFTER trigger
END;

Använda platshållare som %I och %L gör det också möjligt att definiera själva SQL bara en gång och återanvända den. Dessa "parametrar" ersätts av format() funktion (som bevarar $1 )

Observera användningen av ($1).* inuti SQL-strängen. Det gör att execute expandera postparametern $1 till alla dess kolumner. Själva posten skickas "native" med USING nyckelord.

Användningen av INSERT utan en målkolumnlista (insert into some_table ... istället för insert into some_table (col1, col2, ...) ... ) är en ganska bräcklig sak att göra. Om källan och målet inte matchar kan infogningen misslyckas ganska lätt. .

Om du inte kör omfattande rapportering på granskningstabellerna (där att ha explicita kolumnnamn skulle vara mycket effektivare) kanske du vill tänka på en mer generisk granskningsutlösare med en JSON eller HSTORE kolumn för att lagra hela posten. Det finns flera färdiga granskningsutlösare tillgängliga:




  1. sqlite:hur lägger man till total tid hh:mm:ss där kolumndatatypen är DATETIME?

  2. Finns det något sätt att visa en WHERE-sats bara för ett fält i MySQL?

  3. JPA GenerationType.AUTO beaktar inte kolumn med automatisk ökning

  4. Bästa sättet att lagra kvartal och år i SQL Server?