นอกจากสิ่งที่@Craig จัดเตรียมไว้ (และแก้ไขบางส่วนแล้ว):
มีผลบังคับใช้ Postgres 9.4 , UNIQUE
, PRIMARY KEY
และEXCLUDE
ข้อ จำกัด จะถูกตรวจสอบได้ทันทีหลังจากที่แต่ละแถวNOT DEFERRABLE
เมื่อกำหนด ซึ่งแตกต่างจากชนิดอื่น ๆ ของNOT DEFERRABLE
ข้อ จำกัด (ปัจจุบันเท่านั้นREFERENCES
(คีย์ต่างประเทศ)) ซึ่งได้มีการตรวจสอบหลังจากแต่ละคำสั่ง เราทำงานทั้งหมดนี้ภายใต้คำถามที่เกี่ยวข้องนี้ใน SO:
มันเป็นไม่พอสำหรับUNIQUE
(หรือPRIMARY KEY
หรือEXCLUDE
) จำกัด จะเป็นDEFERRABLE
ที่จะทำให้รหัสนำเสนอของคุณด้วยงบหลายงาน
และคุณไม่สามารถใช้ALTER TABLE ... ALTER CONSTRAINT
เพื่อวัตถุประสงค์นี้ ตามเอกสาร:
ALTER CONSTRAINT
แบบฟอร์มนี้จะเปลี่ยนแปลงคุณสมบัติของข้อ จำกัด ที่สร้างขึ้นก่อนหน้านี้ ปัจจุบันข้อ จำกัด ที่สำคัญเท่านั้นต่างประเทศอาจมีการเปลี่ยนแปลง
เหมืองเน้นหนัก ใช้แทน:
ALTER TABLE t
DROP CONSTRAINT category_name_key
, ADD CONSTRAINT category_name_key UNIQUE(name) DEFERRABLE;
ดร็อปและเพิ่มข้อ จำกัด กลับมาในคำสั่งเดียวดังนั้นจึงไม่มีหน้าต่างเวลาสำหรับใครที่จะแอบเข้าไปในแถวที่กระทำผิด สำหรับตารางขนาดใหญ่มันจะดึงดูดการอนุรักษ์ดัชนีที่ไม่ซ้ำกันต้นแบบอย่างใดเพราะมันมีค่าใช้จ่ายสูงในการลบและสร้างใหม่ อนิจจาที่ดูเหมือนจะไม่เป็นไปได้ด้วยเครื่องมือมาตรฐาน (หากคุณมีวิธีแก้ปัญหาโปรดแจ้งให้เราทราบ!):
สำหรับคำสั่งเดียวที่ทำให้การ จำกัด การเลื่อนเวลานั้นเพียงพอแล้ว:
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 ก็เป็นคำสั่งเดียว :
WITH x AS (
UPDATE category SET name = 'phones' WHERE id = 1
)
UPDATE category SET name = 'tablets' WHERE id = 2;
อย่างไรก็ตามสำหรับรหัสของคุณที่มีหลายคำสั่งคุณ (เพิ่มเติม) จำเป็นต้องเลื่อนข้อ จำกัด ออกไป - หรือกำหนดเป็นINITIALLY DEFERRED
Either โดยทั่วไปจะมีราคาแพงกว่าข้างต้น แต่อาจเป็นไปไม่ได้ที่จะบรรจุทุกอย่างลงในคำสั่งเดียว
BEGIN;
SET CONSTRAINTS category_name_key DEFERRED;
UPDATE category SET name = 'phones' WHERE id = 1;
UPDATE category SET name = 'tablets' WHERE id = 2;
COMMIT;
ระวังข้อ จำกัด ที่เกี่ยวข้องกับFOREIGN KEY
ข้อ จำกัด ตามเอกสาร:
คอลัมน์ที่อ้างอิงจะต้องเป็นคอลัมน์ของข้อ จำกัด คีย์ที่ไม่ซ้ำกันหรือคีย์หลักในตารางอ้างอิง
ดังนั้นคุณไม่สามารถมีทั้งสองอย่างในเวลาเดียวกัน