[SQL] 그것은 다른 아이에 의해 참조되어 있지 않은 경우 삭제 부모
SQL그것은 다른 아이에 의해 참조되어 있지 않은 경우 삭제 부모
나는 예를 들어 상황을 가지고 : 부모 테이블은 외래 키로 자식 테이블에서 참조 ID라는 이름의 열이 있습니다.
자식 행을 삭제할 때이 다른 아이에 의해 참조 아니에요 아니라 것처럼, 어떻게 부모를 삭제하려면?
해결법
-
==============================
1.PostgreSQL을 9.1 이상에서는 당신은 데이터 수정 CTE를 사용하여 하나의 문이 작업을 수행 할 수 있습니다. 이것은 일반적으로 더 적은 오류가 발생하기 쉬운입니다. 그것은 경쟁 조건이 동시 작업과 결과를 놀라게으로 이어질 수있는 두 건의 DELETE 사이의 시간 프레임을 최소화 :
PostgreSQL을 9.1 이상에서는 당신은 데이터 수정 CTE를 사용하여 하나의 문이 작업을 수행 할 수 있습니다. 이것은 일반적으로 더 적은 오류가 발생하기 쉬운입니다. 그것은 경쟁 조건이 동시 작업과 결과를 놀라게으로 이어질 수있는 두 건의 DELETE 사이의 시간 프레임을 최소화 :
WITH del_child AS ( DELETE FROM child WHERE child_id = 1 RETURNING parent_id, child_id ) DELETE FROM parent p USING del_child x WHERE p.parent_id = x.parent_id AND NOT EXISTS ( SELECT 1 FROM child c WHERE c.parent_id = x.parent_id AND c.child_id <> x.child_id -- ! );
SQL 바이올린.
아이는 어떤 경우 삭제됩니다. 나는 설명서를 인용 :
그것은 다른 아이가없는 경우, 부모는 삭제됩니다. 마지막 조건을합니다. 사람이 기대하는 것과는 달리,이 때문에 필요하다 :
굵게 강조 광산. 나는 비 설명 ID 대신에 열 이름 PARENT_ID을 사용했다.
나는 완전히 위에서 언급 한 가능한 경쟁 조건을 제거하려면 먼저 부모 행을 잠급니다. 물론, 모든 유사한 작업은 작업하기 위해 같은 절차를 따라야합니다.
WITH lock_parent AS ( SELECT p.parent_id, c.child_id FROM child c JOIN parent p ON p.parent_id = c.parent_id WHERE c.child_id = 12 -- provide child_id here once FOR NO KEY UPDATE -- locks parent row. ) , del_child AS ( DELETE FROM child c USING lock_parent l WHERE c.child_id = l.child_id ) DELETE FROM parent p USING lock_parent l WHERE p.parent_id = l.parent_id AND NOT EXISTS ( SELECT 1 FROM child c WHERE c.parent_id = l.parent_id AND c.child_id <> l.child_id -- ! );
한 번에 하나의 트랜잭션이 방법은 같은 부모를 잠글 수 있습니다. 그것은 그 여러 트랜잭션에게 같은 부모의 삭제 아이가 발생하지 수, 여전히 다른 아이들을보고 모든 아이들이 나중에 갔다하는 동안, 부모를 아끼지. (키가 아닌 컬럼에 대한 업데이트는 여전히위한 NO KEY UPDATE로 사용할 수 있습니다.)
이러한 경우가 발생하지 않습니다 또는 당신이 (좀처럼) 그것으로 살 수있는 경우 발생 - 첫 번째 쿼리가 저렴합니다. 그 밖에,이 보안 경로입니다.
FOR NO KEY UPDATE는 포스트 그레스 9.4에서 도입되었습니다. 매뉴얼의 세부 사항. 이전 버전에서 대신 업데이트에 대한 강한 잠금을 사용합니다.
-
==============================
2.
delete from child where parent_id = 1
아이 삭제 후 부모에 그것을 할 :
delete from parent where id = 1 and not exists ( select 1 from child where parent_id = 1 )
되지는 조건이이 아이에 존재하지 않는 경우에만 삭제됩니다 있는지 확인합니다 존재한다. 당신은 트랜잭션을 모두 삭제 명령을 포장 할 수 있습니다 :
begin; first_delete; second_delete; commit;
from https://stackoverflow.com/questions/15809463/delete-parent-if-its-not-referenced-by-any-other-child by cc-by-sa and MIT license
'SQL' 카테고리의 다른 글
[SQL] 어떻게 각 그룹의 첫 번째 N 행을 선택하려면? (0) | 2020.05.22 |
---|---|
[SQL] 저장 프로 시저 / 함수는 테이블을 반환 할 수 있나요? (0) | 2020.05.22 |
[SQL] 공간을 무시 쿼리 (0) | 2020.05.22 |
[SQL] 오라클 SQL의 맞춤 주문 (0) | 2020.05.22 |
[SQL] 어떻게 오라클 VARCHAR 값의 문자의 발생 수를 계산하려면? (0) | 2020.05.22 |