PostgreSQL yabancı anahtar denetimlerini geçişler için devre dışı bırakın


92

PostgreSQL 9.4'te yabancı anahtarlara sahip birçok geçiş oluşturuyorum.

Bu bir baş ağrısı yaratıyor çünkü tabloların tümü, taşınırken yabancı anahtarların beklediği sırayla aynı olmalıdır. Yeni geçişlerimin bir yabancı anahtara bağlı olduğu diğer paketlerden geçişler yapmak zorunda kalırsam daha da zorlaşıyor.

MySQL'de, bunu yalnızca SET FOREIGN_KEY_CHECKS = 0;geçiş dosyamın en üstüne ekleyerek basitleştirebilirim . Bunu PostgresSQL'de yalnızca geçiş kodunun uzunluğu için geçici olarak nasıl yapabilirim?

BTW, bunun için Laravel Schema Builder'ı kullanıyor.

Yanıtlar:


83

PostgreSQL herhangi bir yapılandırma seçeneğini desteklemez, ancak başka bir olasılık daha vardır.

postgres=# \d b
        Table "public.b"
┌────────┬─────────┬───────────┐
│ Column │  Type   │ Modifiers │
╞════════╪═════════╪═══════════╡
│ id     │ integer │           │
└────────┴─────────┴───────────┘
Foreign-key constraints:
    "b_id_fkey" FOREIGN KEY (id) REFERENCES a(id) DEFERRABLE

Postgres'teki bilgi bütünlüğü, tetikleyiciler tarafından uygulanır ve tablodaki tetikleyicileri devre dışı bırakabilirsiniz. Bu yöntemle herhangi bir veriyi (riski) yükleyebilirsiniz, ancak bu önemli ölçüde daha hızlıdır - çünkü büyük verilerin kontrolü pahalıdır. Ve yüklemeniz güvenliyse, yapabilirsiniz.

BEGIN;
ALTER TABLE b DISABLE TRIGGER ALL;
-- now the RI over table b is disabled
ALTER TABLE b ENABLE TRIGGER ALL;
COMMIT;

Bir sonraki olasılık, ertelenmiş kısıtlamaları kullanmaktır. Bu hareket kısıtlama kontrolü, zamanı işlemek için. Bu nedenle, INSERTkomutlarla düzene saygı göstermemelisiniz :

ALTER TABLE b ALTER CONSTRAINT b_id_fkey DEFERRABLE;

BEGIN
postgres=# SET CONSTRAINTS b_id_fkey DEFERRED;
SET CONSTRAINTS
postgres=# INSERT INTO b VALUES(100); -- this is not in a table
INSERT 0 1
postgres=# INSERT INTO b VALUES(10);
INSERT 0 1 
postgres=# COMMIT;
ERROR:  insert or update on table "b" violates foreign key constraint "b_id_fkey"
DETAIL:  Key (id)=(100) is not present in table "a".

Girilen veriler kontrol edileceği için bu yöntem sizin için tercih edilmelidir.


2
Nedense, bu benim için bir kez çalıştı ve sonra hiç işe yaramadı. AWs aurora postgres'tayım, burada super userrolü kilitlediler, böylece müşteriler çoğaltma ayarlarını bozamaz. Bazı sistem tetikleyicilerini devre dışı bırakmak için süper bir kullanıcı olmam gerekiyor gibi görünüyor. (Şu anda aynı zamanda sahibi olan yönetici hesabımı kullanıyorum - neden bir kez çalıştığından emin değilim.) Çoğaltma seçeneğini ayarlamak da uygun bir seçenek değildir, çünkü bu da super userrolü gerektirir . Tek seçeneğim yabancı anahtarları düşürmek ve yeniden oluşturmak gibi görünüyor ...
ps2goat

Burada aynı. Bir DISABLE TRIGGER ALLşey yapmak , ama hiçbir etkisi yok. Herhangi bir uyarı bile almadım. Sadece görmezden geliniyor.
jayarjo

Amazon RDS'de bu, şu hatayı verir:> izin reddedildi: "RI_ConstraintTrigger_a_23031" bir sistem tetikleyicidir, bu nedenle bu tarif maalesef her durum için değildir :)
kolypto

Yerel veri tabanında da hata var. Veritabanına yönelik tüm ayrıcalıklara sahip kullanıcıyla ** izin reddedildi: "RI_ConstraintTrigger_a_16564" bir sistem tetikleyicidir **
Solo.dmitry

154

Taşıma için, tüm tetikleyicileri aşağıdakilerle devre dışı bırakmak daha kolaydır:

SET session_replication_role = 'replica';

Ve geçişten sonra tümü ile yeniden etkinleştirilebilir

SET session_replication_role = 'origin';

3
Kutsal inek, bu hem daha basit hem de eldeki belirli görev için daha uygun mu? (Evet.)
ijoseph

10
Dikkatli olun: bu, süper kullanıcı ayrıcalıkları gerektirir. "KISITLAMALARI TÜM ERTELENMİŞTİR" seçeneğini deneyin.
JJC

9
Ben varım 10.4ve yukarıdaki ifade işe yaramıyor.
Stephane

2
Birisi bu yöntemin tehlikelerini / risklerini ve hangi senaryolarda kullanılması gerektiğini ve risklerin nasıl azaltılacağını özetleyebilir mi? Bu kötü bir uygulama olarak kabul edilirse en iyi uygulama nedir?
karns

6
Btw, bu parametre veritabanı parametre grubundaki AWS RDS'de ayarlanabilir ve db'yi yeniden başlatmadan uygulanabilir! DMS'yi mevcut şema ve oluşturulmuş kısıtlamalarla boş bir veritabanına kullanıyorsanız çok kullanışlıdır.
Mike Atlas
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.