Wie deaktiviere ich vorübergehend Fremdschlüssel in Amazon RDS PostgreSQL?

10

Ich migriere eine vorhandene Testumgebung zu Amazon RDS PostgreSQL. Das Testframework verfügt über eine Funktion zum erneuten Laden von Daten in bestimmten Tabellen in einen früheren Zustand. Dazu werden Fremdschlüssel deaktiviert, vorhandene Daten gelöscht, der Sicherungsstatus geladen und Fremdschlüssel wieder aktiviert.

Derzeit deaktiviert das Testframework Fremdschlüssel, indem alle Trigger deaktiviert werden (dies erfordert natürlich einen Superuser):

alter table tablename disable trigger all;

Auf RDS schlägt dies fehl mit:

FEHLER: Berechtigung verweigert: "RI_ConstraintTrigger_a_20164" ist ein Systemtrigger

Wie kann ich Fremdschlüssel in Amazon RDS PostgreSQL vorübergehend deaktivieren?

Hinweis: Eine ähnliche Frage wurde bereits gestellt ( PostgreSQL auf RDS: Wie werden Daten mit FK-Einschränkungen in großen Mengen importiert? ), Es ging jedoch speziell um den Offline-Import, und die Lösung ist auch spezifisch für den Offline-Import.

Piotr Findeisen
quelle
Vielleicht sollte dies eine Stackoverflow-Frage sein?
Piotr Findeisen
Nicht einverstanden - es hängt ganz klar mit der Datenbankverwaltung zusammen.
Vérace
Wie deaktivierst du jetzt FKs? Warum erwarten Sie, dass es bei RDS anders ist? Warum versuchen Sie es nicht auch selbst?
Dekso
@dezso, danke für den Kommentar. Klar, ich habe den Code hinzugefügt, der für Nicht-RDS-PostgreSQL verwendet wird.
Piotr Findeisen
Oh ja, so wird es nicht funktionieren. Aber wie wäre es, die FK-Einschränkungen zu löschen und neu zu erstellen?
Dekso

Antworten:

11

session_replication_role

Ich habe eine alternative Möglichkeit zum Deaktivieren von Fremdschlüsseln gefunden - /programming//a/18709987

set session_replication_role = replica;

Und sie wieder aktivieren mit

set session_replication_role = default;

Dies funktioniert auf RDS, erfordert jedoch immer noch ungewöhnliche Berechtigungen (dh nicht standardmäßig gewährt).

FKs löschen und neu erstellen

Eine alternative Lösung besteht darin, wie in den Kommentaren vorgeschlagen, die FKs vorübergehend zu löschen. Dies bringt den zusätzlichen Vorteil, dass Daten überprüft werden, wenn FKs wieder aktiviert werden.

Fallenlassen

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 $$;

Erholung

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
quelle