2010-07-19 4 views
5

연기 가능한 제약 조건 집합을 통해 서로에 대해 의존하는 두 테이블의 행을 삭제하고 싶습니다. 이 게시물을 단순화하기 위해 간단한 DB 스키마를 조롱했습니다.PostgreSQL '지연 가능한 삭제'가 여전히 삭제 제한 조건에 부딪 힙니다.

SQL 트랜잭션/DB 패치 내에서 'delete_from_me'테이블의 항목을 제거하고 싶습니다. catch는, 링크 자체가 풀리기 전에 두 번째 테이블 인 'constraining_table'에서 select를 기반으로 삭제하려고합니다. 여기

tab-quarantine=> \d delete_from_me 
     Table "public.delete_from_me" 
    Column |  Type  | Modifiers 
-----------+-------------------+----------- 
id  | character varying | not null 
extension | character varying | not null 
Indexes: 
    "delete_from_me_pkey" PRIMARY KEY, btree (id) 

tab-quarantine=> \d constraining_table 
    Table "public.constraining_table" 
Column |  Type  | Modifiers 
--------+-------------------+----------- 
image | character varying | not null 
type | character varying | not null 
Foreign-key constraints: 
    "constraining_table_image_fkey" FOREIGN KEY (image) REFERENCES delete_from_me(id) 
     ON UPDATE CASCADE 
     ON DELETE RESTRICT DEFERRABLE 

일부 샘플 난 그냥 거기에 blatted 데이터입니다 : 여기

은 두 테이블의 설명이다

BEGIN; 
\set ON_ERROR_STOP 1 
SET CONSTRAINTS ALL DEFERRED; 
DELETE FROM delete_from_me WHERE id IN (
    SELECT image FROM constraining_table WHERE type = 'select_me' 
); 
DELETE FROM constraining_table WHERE type = 'select_me'; 
COMMIT; 

이 : 여기

tab-quarantine=> SELECT * FROM delete_from_me; 
    id  | extension 
------------+----------- 
12345abcde | png 
(1 row) 

tab-quarantine=> SELECT * FROM constraining_table; 
    image | type 
------------+---------- 
12345abcde | select_me 
(1 row) 

그리고 나의 거래를 간다 트랜잭션이 실패합니다. 이 있다는 것입니다 알고

이 임시 테이블에 대한 좋은 후보처럼 보인다
ERROR: update or delete on table "delete_from_me" violates foreign key constraint "constraining_table_image_fkey" on table "constraining_table" 
DETAIL: Key (id)=(12345abcde) is still referenced from table "constraining_table". 

은, 그러나 내가 좋아하는 것 : 내가 단계별로 수동으로이 작업을 수행 할 때, 나는 다음과 같은 오류 메시지가 표시 해요 제약 조건이 거래가 끝날 때까지 유효하지 않아야한다는 가정하에이 순서대로 삭제할 수 없습니까?

답변

6

ON DELETE RESTRICT DEFERRABLE 대신 ON DELETE NO ACTION DEFERRABLE을 사용하십시오. NO ACTION 대신 RESTRICT을 사용하면 DEFERRABLE 수정 자 적용 여부에 관계없이 제한 조건을 연기 할 수 없게합니다.

이것은 manual page for CREATE TABLE의 글씨입니다 : NO ACTION 검사가 지연되지 않을 수없는 것보다

참조 동작 다른 제약 조건이 연기를 선언하더라도.

명백하게, 위의 경고는 RESTRICT을 포함한다.

NO ACTION

이 삭제 또는 업데이트가 외래 키 제약 조건 위반을 만들 것이라는 점을 나타내는 오류를 생성합니다 :

이 문장은 NO ACTIONRESTRICT의 정의는 직후 다음과 같습니다. 제약 조건이 지연되면 참조 행이 여전히 있으면 제약 조건 확인시이 오류가 생성됩니다. 이는 기본 동작입니다.

이 삭제 또는 업데이트가 외래 키 제약 조건 위반을 만들 것이라는 점을 나타내는 오류를 생성 제한합니다. 이는 수표가 연기 할 수 없다는 점을 제외하고는 NO ACTION과 같습니다. NO ACTION가, 연기가 제외

당신이 볼 수 있듯이

, NO ACTIONRESTRICT 동일하게 동작합니다. 이것이 제가 추천 한 이유입니다 - 당신이 요구하는 바로 그 것 같아요.

관련 문제