SQL Server에서 Cascading을 언제 사용해야하는 이유는 무엇입니까?


149

SQL Server에서 외래 키를 설정할 때 어떤 상황에서 삭제 또는 업데이트시 계단식으로 연결해야하며 그 이유는 무엇입니까?

이것은 아마도 다른 데이터베이스에도 적용됩니다.

나는 각 시나리오의 구체적 예를 위해 무엇보다도 가장 바람직하게 그것을 사용하는 사람으로부터 찾고 있습니다.


4
이 질문은 SQL Server와 관련이없는 것으로 보이며 이론적이고 일반적인 질문처럼 보입니다. sql-server태그 를 제거하면 커뮤니티에 더 유용합니다 .
clapas

4
@clapas 솔직히, 오늘 물어 보면 주제에서 벗어난 것입니다. 커뮤니티에 가치가 있음을 나타내는 높은 조회수 / 투표가 아닌 경우 삭제합니다.
Joel Coehoorn

6
@JoelCoehoorn-분명히 이러한 유형의 질문에는 가치가 있습니다. 이 값은 시간이 지남에 따라 사라지지 않습니다. 내 마음 속에있는 질문은 오늘날 그러한 질문들을 금지함으로써 우리가 잃어버린 가치는 얼마나됩니까?
P.Brian.Mackey

2
@ P.Brian.Mackey 여기, 여기! 내가 본 최고의 질문 / 답변 중 일부는 다운 투표로 선정되었거나 주제를 벗어난 것으로 페인트 된 것입니다 ...
Anthony Griggs

계단식 작업은 직렬화 가능한 잠금을 사용합니다.
Mitch Wheat

답변:


126

지금까지 본 내용 요약 :

  • 어떤 사람들은 계단식을 전혀 좋아하지 않습니다.

캐스케이드 삭제

  • Cascade Delete는 관계의 의미론이 독점적 인 "설명의 일부"를 포함 할 수있을 때 의미가있을 수 있습니다 . 예를 들어, OrderLine 레코드는 상위 주문의 일부이며 OrderLine은 여러 주문간에 공유되지 않습니다. 주문이 사라 졌다면, 주문 라인도 주문해야하며, 주문이없는 라인은 문제가됩니다.
  • Cascade Delete의 일반적인 예는 SomeObject 및 SomeObjectItems입니다. 여기서 해당 주 레코드가 없으면 항목 레코드가 존재하지 않습니다.
  • 당신은해야 하지 당신이 역사를 보존 또는 사용하는 경우 삭제 캐스케이드를 사용하여 "소프트 / 논리적 삭제"당신은 단지 1 / true로 삭제 된 비트 열을 설정 한 경우.

캐스케이드 업데이트

  • 계단식 업데이트는 테이블에서 서로 게이트 키 (ID / 자동 증가 열)가 아닌 실제 키를 사용하는 경우에 적합합니다.
  • Cascade Update의 일반적인 예는 사용자 이름과 같이 변경 가능한 외래 키가있는 경우입니다.
  • ID / 자동 증가 열인 키와 함께 계단식 업데이트를 사용 해서는 안됩니다 .
  • 캐스케이드 업데이트는 고유 제한 조건과 함께 사용하는 것이 가장 좋습니다.

계단식 사용시기

  • 작업을 캐스케이드하기 전에 사용자로부터 다시 강력한 확인을 받고 싶을 수도 있지만 이는 응용 프로그램에 따라 다릅니다.
  • 외래 키를 잘못 설정하면 계단식 배열로 인해 문제가 발생할 수 있습니다. 그러나 그렇게하면 괜찮을 것입니다.
  • 계단식을 이해하기 전에 계단식을 사용하는 것이 현명하지 않습니다. 그러나이 기능은 유용한 기능이므로 시간을내어 이해해야합니다.

3
캐스케이드 업데이트는 "소위"자연 키가 실제로 효과적인 고유 키가 아닌 경우에도 자주 사용됩니다. 실제로 캐스케이드 업데이트는 제대로 표준화되지 않은 데이터베이스 모델에서만 필요하며 지저분한 테이블과 지저분한 코드에 대한 열린 문입니다.
Philippe Grondier

1
중요한 점이 하나 없습니다. 하위 레코드가 많은 경우 계단식으로 인해 큰 성능 문제가 발생할 수 있습니다.
HLGEM

13
@HLGEM-관련성이 보이지 않습니다. 계단식 작업으로 인해 속도가 느려지는 경우 트랜잭션을 롤백해야하는 경우 동등한 수동 프로세스로 인해 동일한 속도가 느려지거나 올바르게 보호되지 않습니다.
Joel Coehoorn

3
IDENTITY 또는 자동 증분 열에 계단식 업데이트가 있는지 여부가 중요한 이유는 무엇입니까? 그 (임의의) 값을 변경할 필요가 없기 때문에 왜 필요 하지 않은지 알 수 있지만 그 중 하나 변경되면 최소한 참조 무결성이 손상되지 않습니다.
Kenny Evitt

3
총알 10 개? 이제 우리는 Joel이 리볼버를 발사하지 않는다는 것을 알고 있습니다.
Neil N

68

외래 키는 데이터베이스의 참조 무결성을 보장하는 가장 좋은 방법입니다. 마술이기 때문에 캐스케이드를 피하는 것은 컴파일러의 마술을 신뢰하지 않기 때문에 모든 것을 어셈블리에 쓰는 것과 같습니다.

나쁜 것은 외래 키를 뒤로 만드는 것과 같이 외래 키를 잘못 사용한다는 것입니다.

Juan Manuel의 예제는 정식 예제입니다. 코드를 사용하면 데이터베이스에 가짜 DocumentItem을 남길 가능성이 더 높습니다.

계단식 업데이트는 예를 들어 사용자 테이블의 기본 키가 이름, 성 조합과 같이 변경할 수있는 것으로 데이터를 참조 할 때 유용합니다. 그런 다음 해당 조합의 변경 사항이 참조되는 곳으로 전파되기를 원합니다.

@Aidan, 당신이 말하는 그 명확성은 비용이 많이 들지 않습니다 . 데이터베이스에 가짜 데이터를 남길 수 있습니다 . 저에게는 보통 DB에 익숙하지 않으며 DB를 사용하기 전에 어떤 FK가 있는지 파악할 수 없기 때문에 그러한 두려움이 생깁니다. 개체가 개념적으로 관련되지 않았거나 역사를 보존 해야하는 곳에서 캐스케이드를 계속 사용하거나 연속적으로 잘못 사용합니다.


7
이런 종류의 '자연'기본 키를 사용하는 것은 처음에는 정말 좋지 않은 생각입니다.
Nick Johnson

4
RE : Aidan에 대한 의견. 아니요, FK에서 CASCADE를 해제해도 가짜 데이터가 남을 가능성이 높아지지 않습니다. 예상보다 명령에 의해 더 많은 데이터가 영향을받을 가능성을 줄이고 코드를 증가시킵니다. FK를 떠나면 전적으로 가짜 데이터가 생길 수 있습니다.
섀넌 세브란스

5
내 경력에서 적어도 두 번은 잘못 이해 된 캐스케이드 삭제로 인한 비즈니스 위협의 결과를 보았으므로 가장 명확한 컷 케이스를 제외하고는 모두 내 자신을 사용하지 못하게되었습니다. 두 경우 모두 실제로 유지 되었어야했던 캐스케이드의 결과로 데이터가 삭제되었으며 정상적인 백업주기가 쉬운 복원 가능성을 상실 할 때까지 누락 된 데이터는 발견되지 않았습니다. Vinko는 순전히 논리적 인 관점에서 정확하지만 캐스케이드를 사용하는 실제 세계에서는 사람의 실수와 예상치 못한 결과를 원합니다.
Cruachan

1
실제로 사용자가 마스터를 삭제하여 사용자가 생각하도록 강요하기 전에 사용자가 마스터 세부 정보의 모든 자식을 명시 적으로 삭제해야한다는 관리 결정이 내려진 시스템을 실제로 코딩했습니다. 논리적으로 캐스케이드를 사용하지 않는 것은 비슷한 종류의 방화입니다.
Cruachan

6
@Cruachan : 규칙은 간단합니다. 부모 데이터 없이는 데이터가 쓸모없는 것처럼 강력하게 관련되어 있지 않으면 계단식 관계를 보증하지 않습니다. 이것은 내가 대답에 대한 마지막 문구에서 다루려고했던 것입니다.
Vinko Vrsalovic

17

계단식 삭제를 사용하지 않습니다.

데이터베이스에서 무언가를 제거하려면 원하는 것을 데이터베이스에 명시 적으로 말하고 싶습니다.

물론 그것들은 데이터베이스에서 사용할 수있는 함수이며, 'order'테이블과 'orderItem'테이블이있는 경우 데이터베이스를 삭제할 때 항목을 지우고 싶을 때 사용할 수 있습니다. 주문.

나는 '매직'이 아닌 코드 (또는 저장 프로 시저)에서 수행하는 명확성을 좋아합니다.

같은 이유로 나는 트리거 팬도 아닙니다.

주의 할 점은 '주문'을 삭제하면 계단식 삭제에서 'orderItem'이 50 개를 제거하더라도 '1 행 영향'보고서가 다시 표시됩니다.


34
기본 키도 제거하지 않겠습니까? 코드에서 고유 한 값을 보장하는 명확성을 얻을 수 있습니다.
MusiGenesis

4
@MusiGenesis, Aidan은 FK 제거를 옹호하지 않았습니다. FK는 여전히 데이터를 보호하지만 CASCADE ON .... 없이는 예기치 않은 마법이 발생하지 않습니다.
섀넌 세브란스

7
@ Vinko : 삭제 및 업데이트에는 기본 의미가 잘 정의되어 있습니다. 더 많은 작업을 수행하기 위해 계단식 또는 트리거를 통해 동작을 변경하면 의도 한 것보다 더 많은 기회가 남습니다. 아니요, 테스트 없이는 작동하지 않으며 데이터베이스가 문서화되어 있습니다. 그러나 코드를 작성하는 동안 모든 문서를 기억합니까? 부모 및 자식 삭제와 같은 상위 수준 의미를 원한다면 SP를 작성하고 사용하는 것보다 더 중요합니다.
Shannon Severance

3
@ 빈코. 마술의 문제는 유능한 개발자 나 DBA의 문제가 아니며, 5 년 후 Joe interen이 DBA가 휴가 중일 때 '단순한'유지 관리 작업을 받았으며,이를 모르는 사람없이 회사 데이터를 망쳐 놓은 사람입니다. 캐스케이드는 그 자리를 차지하지만 배치하기 전에 인적 요소를 포함한 전체 환경을 고려하는 것이 중요합니다.
Cruachan

5
@ Vinko : 왜 'Gasp'SP인가? SP는 데이터베이스가 중요한 회사 자산 인 곳으로가는 길입니다. SP 에 대한 모든 데이터 액세스를 제한 하거나 적어도 Select 이외의 모든 데이터 액세스를 제한하려는 상황에 대한 강력한 논거가 있습니다. stackoverflow.com/questions/1171769/…에서
Cruachan

13

계단식 삭제로 많은 작업을 수행합니다.

데이터베이스에 대해 작업하는 사람이 원치 않는 데이터를 남기지 않을 수 있다는 것을 아는 것이 좋습니다. 종속성이 커지면 Management Studio의 다이어그램에서 제약 조건을 변경하기 때문에 sp 또는 데이터 액세스를 조정할 필요가 없습니다.

즉, 계단식 삭제와 순환 참조에는 1 가지 문제가 있습니다. 이는 계단식 삭제가없는 데이터베이스 부분으로 이어지는 경우가 많습니다.


1
나는 이것이 매우 오래되었다는 것을 알고 있지만 CASCADE DELETE의 순환 참조 문제에 대해 +1합니다.
코드 매버릭 1

2
멍청한 질문을 용서하십시오 : 순환 참조를 받으면 실제로 어떻게됩니까?
Tim Lovell-Smith

10

많은 데이터베이스 작업을 수행하고 계단식 삭제가 유용한 경우는 거의 없습니다. 내가 효과적으로 사용한 것은 야간 작업에 의해 업데이트되는보고 데이터베이스에 있습니다. 마지막 가져 오기 이후에 변경된 최상위 레코드를 삭제 한 다음 수정 된 레코드 및 관련 레코드를 다시 가져 와서 변경된 데이터를 올바르게 가져옵니다. 데이터베이스의 맨 아래에서 맨 위까지 보이는 많은 복잡한 삭제를 작성하지 않아도됩니다.

캐스케이드 삭제는 데이터를 삭제하기 때문에 트리거만큼 나쁘지 않다고 생각하지 않습니다. 트리거에는 모든 종류의 불쾌한 물건이 포함될 수 있습니다.

일반적으로 실제 삭제를 피하고 논리적 삭제 (즉, isDeleted라는 비트 열이 true로 설정 됨)를 대신 사용하십시오.


2
좀 더 배우고 싶어서 논리적 삭제를 강력하게 선호하는 이유는 무엇입니까? 작업중인 데이터와 관련이 있습니까?
Tim Lovell-Smith

9

예를 들어 엔터티 간 종속성이있는 경우를 예로들 수 있습니다. 예 : Document-> DocumentItems (Document를 삭제할 때 DocumentItems는 존재할 이유가 없습니다)


5

참조 PK 레코드가 제거 된 경우 FK가있는 레코드를 제거하려는 경우 계단식 삭제를 사용하십시오. 다시 말해, 참조 레코드없이 레코드가 의미가없는 경우입니다.

캐스케이드 삭제는 null 예외를 발생시키지 않고 기본적으로 죽은 참조를 제거하는 데 유용합니다.


5

캐스케이드 삭제시 :

하위 테이블의 행을 삭제 하려는 경우 해당 테이블이 상위 테이블에서 삭제 된 경우 .

경우 삭제 캐스케이드에 다음 사용되지 않는 오류가 위해 발생합니다 참조 무결성 .

캐스케이드 ON시 :

기본 키의 변경 사항외래 키로 업데이트 하려는 경우


5

과거의 나쁜 경험으로 인해 "On Delete Cascade"(및 기타) 사용을 금지하는 DBA 및 / 또는 "회사 정책"에 대해 들었습니다. 어떤 경우에는 한 남자가 서로를 부르는 세 가지 방아쇠를 썼습니다. 하나의 idjit의 조치로 인해 복구 3 일 동안 트리거가 완전히 금지되었습니다.

물론 일부 하위 데이터를 보존해야하는 경우와 같이 "삭제시 계단식"대신 트리거가 필요합니다. 그러나 다른 경우에는 On Delete 캐스케이드 방법을 사용하는 것이 완벽하게 유효합니다. "삭제시 계단식"의 주요 장점은 모든 하위 항목을 캡처한다는 것입니다. 사용자 지정 작성 트리거 / 저장 프로 시저가 올바르게 코딩되지 않으면 그렇지 않을 수 있습니다.

개발자는 개발 내용과 사양에 따라 결정을 내릴 수 있어야한다고 생각합니다. 나쁜 경험에 근거한 카펫 금지는 기준이되어서는 안됩니다. "절대 사용하지 않음"사고 과정은 드라코 니안입니다. 매번 판단 호출이 필요하며 비즈니스 모델이 변경됨에 따라 변경됩니다.

이것이 개발의 전부가 아닙니까?


나는 그것이 모든 것을 삭제할 것이라고 생각하지 않았다 ... 당신은 기능이 실제로 그것이 말하는 것을 수행한다는 것을 의미합니까? ...
Joel Coehoorn 2016 년

3

코드에서 수행하지 않고 연속 삭제를 수행하는 한 가지 이유는 성능을 향상시키기위한 것입니다.

사례 1 : 계단식 삭제

 DELETE FROM table WHERE SomeDate < 7 years ago;

사례 2 : 계단식 삭제없이

 FOR EACH R IN (SELECT FROM table WHERE SomeDate < 7 years ago) LOOP
   DELETE FROM ChildTable WHERE tableId = R.tableId;
   DELETE FROM table WHERE tableId = R.tableid;
   /* More child tables here */
 NEXT

두 번째로, 계단식 삭제로 하위 테이블을 추가하면 사례 1의 코드가 계속 작동합니다.

관계의 의미가 "일부"인 캐스케이드 만 넣을 것입니다. 그렇지 않으면 다음과 같은 작업을 수행 할 때 일부 바보가 데이터베이스의 절반을 삭제합니다.

DELETE FROM CURRENCY WHERE CurrencyCode = 'USD'

5
사용하는 데이터베이스를 모르는 경우 수동 삭제는 기반으로 설정되어 있지 않기 때문에 계단식 삭제보다 성능이 저하됩니다. 대부분의 datbase에서는 다른 테이블에 대한 조인을 기반으로 삭제할 수 있으므로 레코드를 반복하는 것보다 세트 기반의 훨씬 빠른 삭제가 있습니다.
HLGEM

2

SQL Server에서 명시 적으로 요청하지 않은 삭제 또는 업데이트를 피하려고합니다.

계단식 또는 트리거 사용을 통해. 그들은 버그를 추적하려고 할 때나 성능 문제를 진단 할 때 어느 정도 시간을 허비하는 경향이 있습니다.

내가 사용하는 곳은별로 노력하지 않아도 일관성을 보장하는 것입니다. 동일한 효과를 얻으려면 저장 프로 시저를 사용해야합니다.


2

나는 여기의 다른 사람들과 마찬가지로 캐스케이드 삭제가 실제로 거의 도움이되지 않는다는 것을 알게됩니다 (다른 테이블에서 참조 된 데이터를 삭제하는 것은 그리 큰 일이 아닙니다. 테이블이 많으면 스크립트를 사용하여 간단히 자동화하십시오). 누군가 실수로 캐스케이드하여 복원하기 어려운 중요한 데이터를 삭제하는 경우

내가 사용하는 유일한 경우는 테이블 테이블의 데이터가 엄격하게 제어되고 (예 : 제한된 권한) 확인 된 제어 된 프로세스 (예 : 소프트웨어 업데이트)를 통해서만 업데이트되거나 삭제되는 경우입니다.


1

R의 일부 튜플에서 발견 된 외래 키 값을 제거하는 S의 삭제 또는 업데이트는 다음 세 가지 방법 중 하나로 처리 할 수 ​​있습니다.

  1. 배제
  2. 번식
  3. 무효.

전파를 계단식이라고합니다.

두 가지 경우가 있습니다.

‣ S의 튜플이 삭제 된 경우이를 참조한 R 튜플을 삭제하십시오.

‣ S의 튜플이 업데이트 된 경우이를 참조하는 R 튜플의 값을 업데이트하십시오.


0

다른 버전의 여러 모듈이있는 시스템에서 작업하는 경우 계단식 삭제 항목이 PK 홀더의 일부이거나 소유 된 경우 매우 유용 할 수 있습니다. 그렇지 않으면 모든 모듈이 PK 소유자를 삭제하기 전에 종속 항목을 정리하기 위해 즉시 패치가 필요하거나 외래 키 관계가 완전히 생략되어 정리가 올바르게 수행되지 않으면 시스템에 많은 쓰레기가 남을 수 있습니다.

계단식 삭제가 꽤 오랫동안 권장되지 않은 후 이미 존재하는 두 테이블 사이의 새 교차 테이블에 대한 계단식 삭제 (삭제 교차 만)를 소개했습니다. 데이터가 손실되는 경우에도 그렇게 나쁘지 않습니다.

그러나 열거 형과 같은 목록 테이블에서는 나쁜 점이 있습니다. 누군가가 테이블 "색상"에서 항목 13-노란색을 삭제하면 데이터베이스의 모든 노란색 항목이 삭제됩니다. 또한, 이들은 모두 삭제-삽입-전체 방식으로 업데이트되어 참조 무결성이 완전히 생략됩니다. 물론 그것은 틀렸지 만, 진정한 참조 무결성의 도입이 예기치 않은 부작용의 위험에 처해있는 상태에서 수년 동안 실행되었던 복잡한 소프트웨어를 어떻게 변화시킬 것입니까?

또 다른 문제는 기본 외래 키 값이 기본 키가 삭제 된 후에도 유지되어야하는 경우입니다. 원래 FK에 대해 삭제 표시 열과 ON DELETE SET NULL 옵션을 만들 수 있지만 중복 키 (PK 삭제 후 제외) 키 값을 유지하려면 트리거 또는 특정 코드가 다시 필요합니다.


0

계단식 삭제는 물리적 데이터베이스에서 논리적 슈퍼 유형 및 하위 유형 엔터티를 구현할 때 매우 유용합니다.

별도의 수퍼 유형 및 하위 유형 테이블을 사용하여 수퍼 유형 / 하위 유형을 물리적으로 구현하는 경우 (모든 하위 유형 속성을 단일 물리적 수퍼 유형 테이블로 롤업하는 것과 대조적으로) 일대일 이러한 테이블과 문제 간의 관계는 기본 키를이 테이블간에 100 % 동기화하는 방법이됩니다.

계단식 삭제는 다음과 같은 경우에 매우 유용한 도구입니다.

1) 수퍼 유형 레코드를 삭제하면 해당 단일 하위 유형 레코드도 삭제해야합니다.

2) 하위 유형 레코드를 삭제하면 수퍼 유형 레코드도 삭제해야합니다. 이는 하위 유형 테이블에 "중재하지 않은"삭제 트리거를 구현하여 해당 상위 유형 레코드를 이동하고 삭제하는 방식으로 하위 유형 레코드를 삭제합니다.

이러한 방식으로 계단식 삭제를 사용하면 수퍼 유형 레코드를 먼저 삭제하는지 또는 하위 유형 레코드를 먼저 삭제하는지에 관계없이 고아 슈퍼 유형 또는 하위 유형 레코드가 존재하지 않습니다.


좋은 예입니다. JPA에서는 InheritanceStrategy Joined Table입니다. 1) : 일반적으로, 결합 계층 개체가 삭제 된 시퀀스를 구현하여 먼저 결합 된 부분을 먼저 삭제 한 다음 상위 부분을 삭제하는 지속성 계층 프레임 워크 (EclipseLink, Hibernate 등)를 사용합니다. 그러나 가져 오기 또는 아카이브 작업과 같은보다 기본적인 소프트웨어가있는 경우 상위 부분에서 삭제를 실행하여 엔터티를 삭제하는 것이 편리합니다. 2) 관련 : 동의하지만,이 경우 고객은 자신이 회사의 조인 / 서브 파트에서 작업하고 있음을 이미 알고 있어야합니다.
leo
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.