문제

MSSQL 2005에서 나는 악명 높은 오류 메시지를 강타했습니다.

테이블 YYY에 외래 키 제약 조건 XXX를 도입하면 사이클 또는 여러 캐스케이드 경로가 발생할 수 있습니다. 조치 삭제 삭제 또는 업데이트에서 조치 없음을 지정하거나 다른 외국 키 제약 조건을 수정하십시오.

이제 StackoverFlow에는이 오류 메시지에 대한 몇 가지 주제가 있으므로 이미 솔루션이 있습니다 (제 경우에는 트리거를 사용해야합니다). 그러나 왜 그런 문제가 있는지 궁금합니다.

내가 이해 한 바와 같이, 기본적으로 그들이 피하고 싶은 두 가지 시나리오, 즉 사이클과 여러 경로가 있습니다. 주기는 두 개의 테이블이 서로 계단식을 거치는 곳입니다. 자, 사이클은 여러 테이블에 걸쳐있을 수 있지만 이것은 기본적인 경우이며 분석하기가 더 쉽습니다.

Tablea에 TableB 및 Table에 대한 외국 키가있을 때 여러 경로가 있으며 TableB는 테이블에 대한 외래 키도 있습니다. 다시 - 이것은 최소 기본 사례입니다.

해당 테이블에서 레코드가 삭제되거나 업데이트 될 때 발생하는 문제를 볼 수 없습니다. 물론, 어떤 레코드가 업데이트/삭제가 필요한지 확인하기 위해 동일한 테이블을 여러 번 쿼리해야 할 수도 있지만 실제로 문제입니까? 이것이 성능 문제입니까?

다른 주제에서는 사람들은 캐스케이드를 사용하여 레이블을 붙일 때까지 "위험한"그리고"캐스케이드 경로를 해결하는 것은 복잡한 문제입니다". 왜? 위험은 어디에 있습니까? 문제는 어디에 있습니까?

도움이 되었습니까?

해결책

같은 부모로부터 2 개의 캐스케이드 경로가있는 어린이 테이블이 있습니다 : 하나는 "삭제", 하나는 "null"입니다.

무엇이 우선 하는가? 나중에 무엇을 기대하십니까? 등

참고 : 트리거는 코드이며 캐스케이드에 일부 지능이나 조건을 추가 할 수 있습니다.

다른 팁

Cascade Delete를 사용하는 것을 금지하는 이유는 성능 및 잠금과 관련이 있습니다. 예, 한 레코드를 삭제할 때 나쁘지는 않지만 조만간 많은 레코드 그룹을 삭제해야하며 데이터베이스가 정지됩니다.

충분한 레코드를 삭제하는 경우 SQL Server가 테이블 잠금으로 에스컬레이션 될 수 있으며 아무도 완료 될 때까지 테이블로 아무것도 할 수 없습니다.

우리는 최근 고객 중 하나를 자신의 서버로 옮겼습니다. 거래의 일환으로 우리는 또한 해당 클라이언트의 모든 레코드를 원래 서버를 삭제해야했습니다. 모든 정보를 배치로 삭제하는 데 몇 달이 걸렸습니다. Cascade Delete 설정이 설정되어 있으면 한 번의 거래에서 수백만의 레코드가 삭제되고 거래가 완료 될 때까지 수백 개의 테이블이 잠겨 있기 때문에 데이터베이스는 오랫동안 다른 클라이언트가 접근 할 수 없었을 것입니다.

캐스케이드 경로가 취한 순서를 제어 할 수없고 데이터베이스가 대부분의 테이블에 나타나는 ClientID와 다소 비정규 화되어 있기 때문에 Cascade Delete를 사용하여 교착 상태가 발생할 수있는 시나리오를 볼 수 있습니다. 따라서 외국 키가있는 하나의 테이블을 세 번째 테이블과 다른 경로에있는 클라이언트 테이블에 잠그면 세 번째 테이블에서 삭제하기 위해 해당 테이블을 확인할 수 없었을 것입니다. 하나의 트랜잭션과 잠금 장치가 완료 될 때까지 릴리스되지 않습니다. 따라서 거래에서 교착 상태를 만들 가능성이있는 경우 캐스케이드 삭제를 설정하지 못했을 것입니다.

계단식 삭제를 피하는 또 다른 이유는 때때로 아동 기록의 존재가 부모 레코드를 삭제하지 않는 충분한 이유이기 때문입니다. 예를 들어, 고객 테이블이 있고 고객이 과거에 주문을 한 경우, 그를 삭제하고 실제 주문에 대한 정보를 잃고 싶지 않을 것입니다.

직원 테이블을 고려하십시오.

CREATE TABLE Employee
(
    EmpID   INTEGER NOT NULL PRIMARY KEY,
    Name    VARCHAR(40) NOT NULL,
    MgrID   INTEGER NOT NULL REFERENCES Employee(EmpID) ON DELETE CASCADE
);

INSERT INTO Employees(     1, "Bill",   1);
INSERT INTO Employees(    23, "Steve",  1);
INSERT INTO Employees(234212, "Helen", 23);

이제 Bill 은퇴한다고 가정합니다.

DELETE FROM Employees WHERE Name = "Bill";

ooooppps; 모두가 약탈당했습니다!

[구문의 세부 사항이 올바른지 토론 할 수 있습니다. 개념은 서 있습니다.]

문제는 "Cascade on Delete on Delete"와 "삭제 제한"또는 "결과가 없음"이 예측할 수 없다는 문제가 있다고 생각합니다. 삭제 트리거 (이것은 트리거이기도하지만 스스로를 구축 할 필요가없는 것)에 따라 다릅니다.

나는 캐스케이드가 "위험한"것에 동의하며 피해야한다. (저는 SQL Server가 자동으로 처리하는 대신 개인적으로 변경 사항을 수동으로 계단식으로 캐스케이드하는 것을 선호합니다). SQL Server가 수백만 행을 삭제하더라도 출력이 여전히

(1 열 영향)

A on Delete 캐스케이드 옵션을 사용하는 것이 구현중인 비즈니스 모델의 문제라고 생각합니다. 두 비즈니스 객체 사이의 관계는 관계의 양쪽 끝이 관련되는 간단한 "연관성"일 수 있지만, 다른 독립적 인 객체는 다른 논리에 의해 다르고 제어되는 독립적 인 객체입니다. 그러나 "집계"관계도 있습니다. 여기서 한 객체는 실제로 "자식"또는 "세부 사항"객체의 "부모"또는 "소유자"로 볼 수 있습니다. "구성"관계에 대한 더 강력한 개념이 있으며, 여기서 물체는 다수의 부품의 구성 으로서만 존재합니다. "협회"사례에서는 일반적으로 on 삭제 캐스케이드 제약 조건을 선언하지 않습니다. 그러나 집계 또는 구성의 경우 ON DELETE CASCADE는 비즈니스 모델을 데이터베이스에보다 정확하고 선언적으로 매핑하는 데 도움이됩니다. 그렇기 때문에 SQL Server MS 가이 옵션의 사용을 단일 캐스케이드 경로로 제한한다는 것이 귀찮은 이유입니다. 내가 착각하지 않으면 널리 사용되는 다른 많은 SQL 데이터베이스 시스템은 그러한 제한을 부과하지 않습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top