sql >> Databasteknik >  >> RDS >> PostgreSQL

Utlösare för att infoga rader i fjärrdatabas efter radering

Detta är en begränsad tillämpning av replikering. Kraven varierar mycket, så det finns ett antal olika etablerade lösningar som löser olika situationer. Tänk på översikten i manualen.

Din handstickade, triggerbaserade lösning är ett gångbart alternativ för relativt raderingar. Att öppna och stänga en separat anslutning för varje rad medför en hel del omkostnader. Det finns andra olika alternativ.

Medan arbetar med dblink föreslår jag några ändringar. Viktigast av allt:

  • Använd format() för att undkomma strängar mer elegant.

  • Passera hela raden istället för att passera och fly varenda kolumn.

  • Placera inte lösenordet i varje enskild triggerfunktion.
    Använd en FOREIGN SERVER plus USER MAPPING . Detaljerade instruktioner här:

Kör i princip en gång på källservern:

CREATE SERVER myserver FOREIGN DATA WRAPPER dblink_fdw
OPTIONS (hostaddr '127.0.0.1', dbname 'gtr_bd_archive');

CREATE USER MAPPING FOR role_source SERVER myserver
OPTIONS (user 'postgres', password 'secret');

Logga helst inte in som superanvändare på målservern. Använd en dedikerad roll med begränsade privilegier för att undvika privilegieskalering.

Och använd en lösenordsfil på målservern för att tillåta lösenordslös åtkomst. På så sätt behöver du inte ens lagra lösenordet i USER MAPPING . Instruktioner i det sista kapitlet i detta relaterade svar:

Sedan:

CREATE OR REPLACE FUNCTION pg_temp.flux_tresorerie_historique_backup_row()
  RETURNS trigger AS
$func$
BEGIN
   PERFORM dblink_connect('myserver');  -- name of foreign server from above

   PERFORM dblink_exec( format(
   $$
   INSERT INTO flux_tresorerie_historique  -- provide target column list!
   SELECT (r).id_flux_historique
        , (r).date_operation_flux
        , (r).date_valeur_flux
        , (r).date_rapprochement_flux::date  -- 'YYYY-MM-DD' is default ISO format anyway
        , (r).libelle_flux
        , (r).montant_flux
        , (r).contre_valeur_dzd
        , (r).rib_compte_bancaire
        , (r).frais_flux
        , (r).sens_flux
        , (r).statut_flux
        , (r).code_devise
        , (r).code_mode_paiement
        , (r).code_agence
        , (r).code_compte
        , (r).code_banque
        , (r).date_maj_flux
        , (r).statut_frais
        , (r).reference_flux
        , (r).code_commission
        , (r).id_flux
   FROM   (SELECT %L::flux_tresorerie_historique) t(r)
   $$, OLD::text));  -- cast whole row type

   PERFORM dblink_disconnect();
   RETURN NULL;  -- only for AFTER trigger
END
$func$  LANGUAGE plpgsql;

Du bör skriva ut listan med kolumner för måltabellen om radtyperna inte matchar.

Om du menar allvar med detta:

Dvs du infogar hela raden och målradtypen är identisk (ingen extrahering av ett datum från en tidsstämpel etc.), kan du förenkla mycket ytterligare genom att passera hela raden.

CREATE OR REPLACE FUNCTION flux_tresorerie_historique_backup_row()
  RETURNS trigger AS
$func$
BEGIN
   PERFORM dblink_connect('myserver');  -- name of foreign server

   PERFORM dblink_exec( format(
   $$
   INSERT INTO flux_tresorerie_historique
   SELECT (%L::flux_tresorerie_historique).*
   $$
   , OLD::text));

   PERFORM dblink_disconnect();
   RETURN NULL;  -- only for AFTER trigger
END
$func$  LANGUAGE plpgsql;

Relaterat:



  1. Fyll saknade luckor i datumintervallfrågan med hjälp av kalendertabellen

  2. Trädvyskontroll Markera Lägg till Ta bort noder

  3. PostgreSQL:förbättrar pg_dump, pg_restore prestanda

  4. Problem med anslutningspool