Как временно отключить внешние ключи в Amazon RDS PostgreSQL?

10

Я перевожу существующую тестовую среду на Amazon RDS PostgreSQL. Тестовая структура имеет функцию перезагрузки данных в определенных таблицах в более раннее состояние. Для этого он отключает внешние ключи, удаляет существующие данные, загружает состояние сохранения и снова включает внешние ключи.

В настоящее время тестовая среда отключает внешние ключи, отключая все триггеры (конечно, для этого требуется суперпользователь):

alter table tablename disable trigger all;

На RDS это терпит неудачу с:

ОШИБКА: разрешение отклонено: «RI_ConstraintTrigger_a_20164» является системным триггером

Как временно отключить внешние ключи в Amazon RDS PostgreSQL?

Примечание: подобный вопрос уже задавался ( PostgreSQL на RDS: как выполнить массовый импорт данных с ограничениями FK? ), Но он был конкретно об автономном импорте, и решение относится также к автономному импорту.

Петр Финдейзен
источник
Возможно, это должен быть вопрос переполнения стека?
Петр Финдейзен
Не согласен - это очень четко связано с администрированием базы данных.
Vérace
Как вы отключите FKs сейчас? Почему вы ожидаете, что на RDS все будет иначе? Кроме того, почему бы не попробовать себя?
Dezso
@dezso, спасибо за комментарий. Конечно, я добавил код, который используется в PostgreSQL без RDS.
Петр Финдейзен
О да, так не получится. Но как насчет удаления и воссоздания ограничений FK?
Дезсо

Ответы:

11

session_replication_role

Я нашел альтернативный способ отключения внешних ключей - https://stackoverflow.com/a/18709987

set session_replication_role = replica;

И снова включить их

set session_replication_role = default;

Это работает на RDS, но все еще требует необычных привилегий (т.е. не предоставляется по умолчанию).

сброс и воссоздание ФК

Альтернативное решение, как предлагается в комментариях, временно отбросить FK. Это дает дополнительное преимущество в том, что данные проверяются при повторном включении FK.

сбрасывание

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

Воссоздание

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 $$;
Петр Финдейзен
источник