@Craig가 제공 한 것 외에도 일부를 수정합니다.
효과적인 포스트 그레스 9.4 , UNIQUE
, PRIMARY KEY
및 EXCLUDE
제약 즉시 체크 각 행 후 정의 할 때 NOT DEFERRABLE
. 이것은 각 문장마다 확인 되는 다른 종류의 NOT DEFERRABLE
제약 (현재는 REFERENCES
(외부 키)) 과 다릅니다 . 우리는 SO에 관한이 관련 질문에 따라이 모든 것을 해결했습니다.
그것은 것입니다 하지 A에 대한 충분한 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;
제약 조건을 단일 문 에 삭제하고 다시 추가하면 문제가되는 행을 몰래 숨길 시간 창이 없습니다. 큰 테이블의 경우 기본 고유 인덱스를 삭제하고 다시 작성하는 데 비용이 많이 들기 때문에 어떻게 든 기본 인덱스를 보존하려고합니다. 아아, 그것은 표준 도구로는 가능하지 않은 것 같습니다 (해결책이 있으면 알려주십시오!).
A에 대한 하나의 문 제약, 연기하기에 충분하다 :
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
위의 값보다 일반적으로 더 비싼 것으로 정의해야 합니다. 그러나 모든 것을 하나의 문장으로 묶는 것은 쉽지 않을 수 있습니다.
BEGIN;
SET CONSTRAINTS category_name_key DEFERRED;
UPDATE category SET name = 'phones' WHERE id = 1;
UPDATE category SET name = 'tablets' WHERE id = 2;
COMMIT;
(A)의주의 제한 과 관련 FOREIGN KEY
있지만, 제약. 문서 당 :
참조 된 컬럼은 참조 된 테이블에서 지연 불가능한 고유 또는 기본 키 제한 조건의 컬럼이어야 합니다.
따라서 두 가지를 동시에 가질 수는 없습니다.