Jak tymczasowo wyłączyć klucze obce w Amazon RDS PostgreSQL?

10

Przeprowadzam migrację istniejącego środowiska testowego do Amazon RDS PostgreSQL. Struktura testowa ma funkcję przeładowywania danych w niektórych tabelach do wcześniejszego stanu. W tym celu wyłącza klucze obce, usuwa istniejące dane, ładuje stan zapisywania i ponownie włącza klucze obce.

Obecnie środowisko testowe wyłącza klucze obce, wyłączając wszystkie wyzwalacze (oczywiście wymaga to administratora):

alter table tablename disable trigger all;

W przypadku RDS nie działa to z:

BŁĄD: odmowa dostępu: „RI_ConstraintTrigger_a_20164” jest wyzwalaczem systemowym

Jak mogę tymczasowo wyłączyć klucze obce w Amazon RDS PostgreSQL?

Uwaga: podobne pytanie zostało już zadane ( PostgreSQL na RDS: jak zbiorczo importować dane z ograniczeniami FK? ), Ale dotyczyło to w szczególności importu offline, a rozwiązanie dotyczy także importu offline.

Piotr Findeisen
źródło
Być może powinno to być pytanie o przepełnienie stosu?
Piotr Findeisen,
Nie zgadzam się - jest to bardzo wyraźnie związane z administrowaniem bazą danych.
Vérace,
Jak teraz wyłączyć FK? Dlaczego spodziewasz się, że będzie inaczej w RDS? A może warto spróbować?
dezso,
@dezso, dzięki za komentarz. Oczywiście dodałem kod, który jest używany w PostgreSQL innym niż RDS.
Piotr Findeisen,
O tak, w ten sposób to nie zadziała. Ale co powiesz na usunięcie i odtworzenie ograniczeń FK?
dezso

Odpowiedzi:

11

rola_replikacji_sesji

Znalazłem alternatywny sposób wyłączania kluczy obcych - https://stackoverflow.com/a/18709987

set session_replication_role = replica;

I ponownie je włączając

set session_replication_role = default;

Działa to na RDS, ale nadal wymaga nietypowych uprawnień (tzn. Domyślnie nie jest przyznawanych).

upuszczanie i odtwarzanie plików FK

Alternatywnym rozwiązaniem jest, jak sugerowano w komentarzach, tymczasowe upuszczenie FK. Daje to dodatkową korzyść polegającą na weryfikacji danych po ponownym włączeniu FK.

Rzut

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

Odtwarzanie

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
źródło