Bagaimana cara menonaktifkan sementara kunci asing di Amazon RDS PostgreSQL?

10

Saya memigrasikan lingkungan pengujian yang ada ke Amazon RDS PostgreSQL. Kerangka uji memiliki fitur memuat ulang data dalam tabel tertentu ke keadaan sebelumnya. Untuk ini ia menonaktifkan kunci asing, menghapus data yang ada, memuat negara menyimpan dan mengaktifkan kunci asing lagi.

Saat ini, kerangka uji menonaktifkan kunci asing dengan menonaktifkan semua pemicu (tentu saja, ini membutuhkan superuser):

alter table tablename disable trigger all;

Pada RDS, ini gagal dengan:

GALAT: izin ditolak: "RI_ConstraintTrigger_a_20164" adalah pemicu sistem

Bagaimana saya dapat menonaktifkan sementara kunci asing di Amazon RDS PostgreSQL?

Catatan: pertanyaan serupa telah ditanyakan ( PostgreSQL di RDS: Bagaimana cara mengimpor data massal dengan batasan FK? ) Tapi itu khusus tentang impor offline dan solusinya juga khusus untuk impor offline.

Piotr Findeisen
sumber
Mungkin ini seharusnya menjadi pertanyaan stackoverflow?
Piotr Findeisen
Tidak setuju - ini sangat jelas terkait dengan administrasi basis data.
Vérace
Bagaimana Anda menonaktifkan FK sekarang? Mengapa Anda mengharapkannya berbeda pada RDS? Juga, mengapa tidak mencoba sendiri?
dezso
@dezso, terima kasih atas komentarnya. Tentu, saya menambahkan kode yang digunakan pada PostgreSQL non-RDS.
Piotr Findeisen
Oh ya, cara ini tidak akan berhasil. Tetapi bagaimana dengan menjatuhkan dan menciptakan kembali batasan-batasan FK?
dezso

Jawaban:

11

session_replication_role

Saya menemukan cara alternatif untuk menonaktifkan kunci asing - https://stackoverflow.com/a/18709987

set session_replication_role = replica;

Dan mengaktifkan kembali mereka dengan

set session_replication_role = default;

Ini berfungsi pada RDS tetapi masih membutuhkan hak istimewa yang tidak biasa (yaitu tidak diberikan secara default).

menjatuhkan dan menciptakan kembali FK

Solusi alternatif adalah, seperti yang disarankan dalam komentar, untuk sementara waktu menjatuhkan FK. Ini membawa keuntungan tambahan bahwa data diverifikasi ketika FK diaktifkan kembali.

Jatuhan

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

Rekreasi

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
sumber