Comment désactiver temporairement les clés étrangères dans Amazon RDS PostgreSQL?

10

Je migre l'environnement de test existant vers Amazon RDS PostgreSQL. Le cadre de test a la particularité de recharger les données de certaines tables dans un état antérieur. Pour cela, il désactive les clés étrangères, supprime les données existantes, charge l'état de sauvegarde et active à nouveau les clés étrangères.

Actuellement, le framework de test désactive les clés étrangères en désactivant tous les déclencheurs (bien sûr, cela nécessite un superutilisateur):

alter table tablename disable trigger all;

Sur RDS, cela échoue avec:

ERREUR: autorisation refusée: "RI_ConstraintTrigger_a_20164" est un déclencheur système

Comment puis-je désactiver temporairement les clés étrangères dans Amazon RDS PostgreSQL?

Remarque: une question similaire a déjà été posée ( PostgreSQL sur RDS: comment importer en masse des données avec des contraintes FK? ) Mais il s'agissait spécifiquement de l'importation hors ligne et la solution est également spécifique à l'importation hors ligne.

Piotr Findeisen
la source
Peut-être que cela devrait être une question de stackoverflow?
Piotr Findeisen le
Pas d'accord - c'est très clairement lié à l'administration de la base de données.
Vérace
Comment désactivez-vous les FK maintenant? Pourquoi pensez-vous que ce sera différent sur RDS? Aussi, pourquoi ne pas vous essayer?
dezso
@dezso, merci pour le commentaire. Bien sûr, j'ai ajouté le code utilisé sur PostgreSQL non RDS.
Piotr Findeisen
Oh oui, de cette façon, cela ne fonctionnera pas. Mais que diriez-vous de supprimer et recréer les contraintes FK?
dezso

Réponses:

11

session_replication_role

J'ai trouvé un autre moyen de désactiver les clés étrangères - https://stackoverflow.com/a/18709987

set session_replication_role = replica;

Et les réactiver avec

set session_replication_role = default;

Cela fonctionne sur RDS mais nécessite toujours des privilèges inhabituels (c'est-à-dire non accordés par défaut).

suppression et recréation de FK

Une solution alternative consiste, comme suggéré dans les commentaires, à supprimer temporairement les FK. Cela apporte un avantage supplémentaire: les données sont vérifiées lorsque les FK sont réactivés.

Goutte

create table if not exists dropped_foreign_keys (
        seq bigserial primary key,
        sql text
);

do $$ declare t record;
begin
    for t in select conrelid::regclass::varchar table_name, conname constraint_name,
            pg_catalog.pg_get_constraintdef(r.oid, true) constraint_definition
            from pg_catalog.pg_constraint r
            where r.contype = 'f'
            -- current schema only:
            and r.connamespace = (select n.oid from pg_namespace n where n.nspname = current_schema())
        loop

        insert into dropped_foreign_keys (sql) values (
            format('alter table %s add constraint %s %s',
                quote_ident(t.table_name), quote_ident(t.constraint_name), t.constraint_definition));

        execute format('alter table %s drop constraint %s', quote_ident(t.table_name), quote_ident(t.constraint_name));

    end loop;
end $$;

Recréer

do $$ declare t record;
begin
    -- order by seq for easier troubleshooting when data does not satisfy FKs
    for t in select * from dropped_foreign_keys order by seq loop
        execute t.sql;
        delete from dropped_foreign_keys where seq = t.seq;
    end loop;
end $$;
Piotr Findeisen
la source