계층 적 데이터가있는 테이블이 있습니다.
부모의 ID ("ID"- 키 열)를 보유하는 열 "ParentId"입니다.SQL 테이블의 계층 적 데이터 삭제
행을 삭제할 때 모든 하위 항목 (모든 중첩 수준)을 삭제하려고합니다.
어떻게 만드시겠습니까?
감사합니다.
계층 적 데이터가있는 테이블이 있습니다.
부모의 ID ("ID"- 키 열)를 보유하는 열 "ParentId"입니다.SQL 테이블의 계층 적 데이터 삭제
행을 삭제할 때 모든 하위 항목 (모든 중첩 수준)을 삭제하려고합니다.
어떻게 만드시겠습니까?
감사합니다.
행 수가 너무 많지 않으면 erikkallen의 재귀 적 접근 방식이 작동합니다.
여기에 모든 어린이를 수집하기 위해 임시 테이블을 사용하는 대안이다 :
create table #nodes (id int primary key)
insert into #nodes (id) values (@delete_id)
while @@rowcount > 0
insert into #nodes
select distinct child.id
from table child
inner join #nodes parent on child.parentid = parent.id
where child.id not in (select id from #nodes)
delete
from table
where id in (select id from #nodes)
그것은 @delete_id있는 행으로 시작하고 거기에서 내려. where 문은 재귀로부터 보호합니다. 아무 것도 없다고 확신하는 경우, 그것을 버릴 수 있습니다.
계층 구조를 저장하는 방법에 따라 다릅니다. ParentID 만 가지고 있다면 가장 효과적인 접근 방법이 아닐 수도 있습니다.
where Parents like @NodeParents + '%'
: 당신은 단순히 모든 하위 노드를 얻을 수 있습니다
/1/20/25/40
이 방법 : 하위 트리 조작의 용이성을 위해 당신은 같은 모든 상위 ID를 저장 wouls 추가 열 Parents
을 가져야한다 두 번째 접근 방식
단지 ParentID 대신 left
및 right
값을 가질 수도 있습니다. 이 방법으로 삽입하는 것은 느리지 만 선택 작업은 매우 빠릅니다. 당신은 SQL 2008을 사용하는 경우 SQL에게 2005 +
네 번째 접근 방식
를 사용하는 경우 특히 http://en.wikipedia.org/wiki/Tree_traversal
세 번째 방법 ... 하위 트리 노드와
체크 재귀 열팽창 계수를 처리 할 때, HIERARCHYID 유형을 확인 . 그것은 당신의 사건에 대한 충분한 가능성을 제공합니다. http://msdn.microsoft.com/en-us/magazine/cc794278.aspx
은 NO, 나는 열에서 전체 부모 체인을 저장하지 않습니다, 거기에 일정한 부모가 참여하고 변화하기 때문이다. 그리고 모든 것을 추적하는 것은 어려울 것입니다. 지금 당장은 할 수 없습니까? – markiz
계층 구조 데이터에 대한 기본 작업은 무엇입니까? 삽입, 업데이트 또는 읽기입니까? –
나는 첫 번째 접근법에 동의하는 경향이 있습니다. 우리는 같은 일을하는 계층 적 데이터의 테이블을 가지고 있습니다. 자녀를 없애는 데 도움이되며 트리의 경로 기반 처리 (예 : 계산을 위해 부모의 모든 하위 항목을 빠르게 반환해야하는 경우)를 수행해야하는 경우에도 도움이됩니다. 원래이 기능을 유지하기 위해 트리거를 사용해 보았지만 대용량 데이터를 추가 할 때 성능에 미치는 영향은 매우 컸습니다. –
가 삭제 등을위한 myTable에에 트리거 TD_MyTable을 만들이
같은 테이블에 트리거를 추가 - 아이들의 한 단계를 삭제 D.ID에 myTable에 M 가입 삭제 D 내부에서 M을 삭제 = M.ID
각 삭제는 동일한 테이블에서 반복적으로 트리거를 호출하여 삭제를 호출합니다. 추가 규칙은 온라인에서 책을 확인하십시오. 트리거가 중첩 될 수있는 횟수에는 제한이있을 수 있습니다.
ST
데이터베이스에 따라 다릅니다. Oracle을 사용하는 경우, 당신이 뭔가를 할 수 있습니다 :
DELETE FROM Table WHERE ID IN (
SELECT ID FROM Table
START WITH ID = id_to_delete
CONNECT BY PRIOR.ID = ParentID
)
ETA : CONNECT BY없이
, 그것은 조금 난이도가 도착합니다. 다른 사람들이 제안했듯이, 트리거 또는 계단식 삭제 제한이 아마도 가장 쉽습니다.
MS SQL SERVER 2005 express – markiz
외래 키 제약 조건을 추가하십시오. 다음 예제는 MySQL은 (syntax reference) 작동 :
ALTER TABLE yourTable
ADD CONSTRAINT makeUpAConstraintName
FOREIGN KEY (ParentID) REFERENCES yourTable (ID)
ON DELETE CASCADE;
이 데이터베이스 수준에서 작동, DBMS의이 행이 너무 모든 참조 행이 삭제됩니다 삭제되면 다음 사항을 확인합니다.
자기 참조 계단식 삭제는 SQL Server 2005에서 지원되지 않습니다. "자식"행이있는 행을 삭제하려고하면 오류가 발생합니다. –
필자는이 답변을 작성한 시점에서 DBMS를 지정하지 않았습니다. 나는 그것을 참조로 남겨 둘 것이다. – soulmerge
아, 그 정도면 충분합니다. 명확히 해 주셔서 감사합니다. –
SQL Server : 재귀 쿼리를 사용하십시오. , 표 TMP (아이디 INT, 부모 int)를 CREATE
WITH x(Id) AS (
SELECT @Id
UNION ALL
SELECT tmp.Id
FROM tmp
JOIN x ON tmp.Parent = x.Id
)
DELETE tmp
FROM x
JOIN tmp ON tmp.Id = x.Id
트리거는 32 레벨 깊은 이하의 계층 구조에 사용할 수 있습니다
예보다 성능이 우수하다면 정말 놀랍습니다. 최대 레벨 깊이는 약 8,9입니다. 어쨌든 데이터베이스에서 실행되는 모든 삭제 명령에서 트리거를 활성화 할 필요가 없기 때문에 트리거를 사용하지 않을 것이라고 생각합니다. – markiz
나는 그것을 시도 할 것입니다 – markiz
나는 SQL에서 그렇게 강력하지 않습니다. 그래서 나는 다음과 같이 질문한다 : 왜 "id from @delete_id"테이블에서 id를 선택해야합니까? @delete_id를 값으로 사용할 수없는 이유는 무엇입니까? – markiz
@markiz : 좋은 지적, 나는 대답을 편집 할 것이다! – Andomar