sql >> Database >  >> RDS >> PostgreSQL

Hoe gegevens met komma's in verschillende tekens op te slaan die door een trigger gaan?

U kunt format() . gebruiken om het maken van een dynamische SQL-query veel gemakkelijker te maken, omdat het automatisch correct omgaat met identifiers en letterlijke waarden. Een ding dat mensen meestal over het hoofd zien, is dat u een enkele recorduitdrukking kunt uitbreiden naar alle kolommen met behulp van (...).* - dit werkt ook voor NEW en OLD registreer variabelen in een trigger, b.v. select (new).*

U kunt ook variabelen doorgeven aan een dynamische SQL met de using trefwoord van de execute uitspraak. Het is niet nodig om het record heen en weer te converteren tussen een record en een tekstweergave.

Met behulp van die mogelijkheid kan uw triggerfunctie worden vereenvoudigd tot:

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;

Plaatsaanduidingen gebruiken zoals %I en %L maakt het ook mogelijk om de eigenlijke SQL slechts één keer te definiëren en opnieuw te gebruiken. Die "parameters" worden vervangen door het format() functie (die de $1 . behoudt )

Let op het gebruik van ($1).* binnen de SQL-string. Dat maakt de execute statement breid de recordparameter uit $1 naar al zijn kolommen. Het record zelf wordt "native" doorgegeven met de USING zoekwoord.

Het gebruik van INSERT zonder een doelkolomlijst (insert into some_table ... in plaats van insert into some_table (col1, col2, ...) ... ) is een vrij kwetsbaar iets om te doen. Als de bron en het doel niet overeenkomen, kan de invoeging vrij gemakkelijk mislukken. .

Als u geen massale rapportage uitvoert op de controletabellen (waar het hebben van expliciete kolomnamen veel efficiënter zou zijn), wilt u misschien een meer generieke controletrigger bedenken met behulp van een JSON of HSTORE kolom om het hele record op te slaan. Er zijn verschillende kant-en-klare audittriggers beschikbaar:




  1. orakel alleen tijd invoegen

  2. Query invoegen, controleren of record bestaat - Zo niet, voeg het dan in

  3. Index maken voor dynamische zoekstrings

  4. Hoe verander ik een PG-kolom in NULLABLE TRUE?