@Craig'in sağladığı şeye ek olarak (ve bazılarını düzeltir):
Etkili Postgres 9.4 , UNIQUE
, PRIMARY KEY
ve EXCLUDE
kısıtlamalar hemen kontrol edilir , her satır sonra tanımlandığı zaman NOT DEFERRABLE
. Bu, her ifadeden sonra kontrol edilen diğer NOT DEFERRABLE
kısıtlama türlerinden (şu anda sadece REFERENCES
(yabancı anahtar)) farklıdır . Tüm bunları SO ile ilgili bu soru altında çalıştık:
Öyle değil bir yeterli UNIQUE
(veya PRIMARY KEY
veya EXCLUDE
) kısıt olarak DEFERRABLE
birlikte sunulan kodunu yapmak için birden fazla ifadeleri çalışması.
Ve yapabilirsiniz değil kullanmak ALTER TABLE ... ALTER CONSTRAINT
bu amaçla. Belgelere göre:
ALTER CONSTRAINT
Bu form, önceden oluşturulmuş bir kısıtlamanın niteliklerini değiştirir. Şu anda yalnızca yabancı anahtar kısıtlamaları değiştirilebilir .
Cesur vurgu benim. Bunun yerine kullanın:
ALTER TABLE t
DROP CONSTRAINT category_name_key
, ADD CONSTRAINT category_name_key UNIQUE(name) DEFERRABLE;
Sınırı tek bir ifadeye bırakın ve ekleyin, böylece kimsenin rahatsız edici satırlara gizlice girmesi için zaman penceresi kalmaz. Büyük tablolar için, temeldeki benzersiz dizini bir şekilde korumak cazip gelebilir, çünkü onu silmek ve yeniden oluşturmak pahalıya mal olur. Ne yazık ki, bu standart araçlarla mümkün görünmüyor (bunun için bir çözümünüz varsa, lütfen bize bildirin!):
Bir İçin Tek açıklamada kısıtlama ertelenebilir hale yeterlidir:
UPDATE category c
SET name = c_old.name
FROM category c_old
WHERE c.id IN (1,2)
AND c_old.id IN (1,2)
AND c.id <> c_old.id;
CTE'lerle yapılan bir sorgu da tek bir ifadedir:
WITH x AS (
UPDATE category SET name = 'phones' WHERE id = 1
)
UPDATE category SET name = 'tablets' WHERE id = 2;
Bununla birlikte , birden fazla ifadeye sahip kodunuz için (ek olarak) kısıtlamayı gerçekten ertelemeniz gerekir - ya da her INITIALLY DEFERRED
ikisinden biri genellikle yukarıdakilerden daha pahalıdır. Ancak her şeyi tek bir ifadeye toplamak kolay olmayabilir.
BEGIN;
SET CONSTRAINTS category_name_key DEFERRED;
UPDATE category SET name = 'phones' WHERE id = 1;
UPDATE category SET name = 'tablets' WHERE id = 2;
COMMIT;
Bununla birlikte, kısıtlamalarla ilgili bir sınırlamanın farkında olun FOREIGN KEY
. Belgelere göre:
Başvurulan sütunlar başvurulan tablodaki ertelenemez benzersiz veya birincil anahtar kısıtlamasının sütunları olmalıdır .
Yani ikisine de aynı anda sahip olamazsınız.