PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Déclencheur pour insérer des lignes dans la base de données distante après la suppression

Il s'agit d'une application limitée de la réplication. Les exigences varient beaucoup, il existe donc un certain nombre de solutions établies différentes, répondant à différentes situations. Considérez l'aperçu du manuel.

Votre solution artisanale basée sur des déclencheurs est une option viable pour relativement peu suppressions. L'ouverture et la fermeture d'une connexion distincte pour chaque ligne entraîne une surcharge importante. Il existe d'autres options.

Pendant que travailler avec dblink je suggère quelques modifications. Le plus important :

  • Utilisez format() pour échapper les chaînes plus élégamment.

  • Passez la ligne entière au lieu de passer et d'échapper à chaque colonne.

  • Ne placez pas le mot de passe dans chaque fonction de déclenchement.
    Utilisez un FOREIGN SERVER plus USER MAPPING . Instructions détaillées ici :

Fondamentalement, exécutez une fois sur le serveur source :

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');

De préférence, ne vous connectez pas en tant que superutilisateur sur le serveur cible. Utilisez un rôle dédié avec des privilèges limités pour éviter l'escalade des privilèges.

Et utilisez un fichier de mot de passe sur le serveur cible pour permettre un accès sans mot de passe. De cette façon, vous n'avez même pas besoin de stocker le mot de passe dans le USER MAPPING . Instructions dans le dernier chapitre de cette réponse connexe :

Ensuite :

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;

Vous devez épeler la liste des colonnes de la table cible si les types de lignes ne correspondent pas.

Si vous êtes sérieux à ce sujet :

C'est-à-dire que vous insérez la ligne entière et que le type de ligne cible est identique (pas d'extraction de date à partir d'un horodatage, etc.), vous pouvez simplifier beaucoup plus en passant toute la ligne.

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;

Connexe :