수색…


ON 캐스케이드 삭제

방을 관리하는 응용 프로그램이 있다고 가정합니다.
응용 프로그램이 클라이언트별로 작동한다고 가정하십시오 (임차인).
여러 고객이 있습니다.
따라서 데이터베이스에는 클라이언트 용 테이블 하나와 회의실 용 테이블 하나가 포함됩니다.

자, 모든 클라이언트는 N 개의 방이 있습니다.

이는 클라이언트 테이블을 참조하여 방 테이블에 외래 키가 있음을 의미합니다.

ALTER TABLE dbo.T_Room  WITH CHECK ADD  CONSTRAINT FK_T_Room_T_Client FOREIGN KEY(RM_CLI_ID)
REFERENCES dbo.T_Client (CLI_ID)
GO

클라이언트가 다른 소프트웨어로 이동한다고 가정하면 소프트웨어에서 그의 데이터를 삭제해야합니다. 하지만 그렇게한다면

DELETE FROM T_Client WHERE CLI_ID = x 

그런 다음 클라이언트에 방이있을 때 클라이언트를 삭제할 수 없으므로 외래 키 위반이 발생합니다.

이제 클라이언트를 삭제하기 전에 클라이언트 방을 삭제하는 코드를 응용 프로그램에 작성해야합니다. 앞으로는 응용 프로그램의 기능이 확장되어 더 많은 외래 키 종속성이 데이터베이스에 추가 될 것이라고 추측하십시오. 끔찍해. 데이터베이스의 모든 수정에 대해 응용 프로그램의 코드를 N 개 장소에 적용해야합니다. 다른 응용 프로그램에서도 코드를 조정해야 할 수 있습니다 (예 : 다른 시스템의 인터페이스).

코드에서 수행하는 것보다 나은 솔루션이 있습니다.
외래 키에 ON DELETE CASCADE 를 추가하기 만하면됩니다.

ALTER TABLE dbo.T_Room  -- WITH CHECK -- SQL-Server can specify WITH CHECK/WITH NOCHECK
ADD  CONSTRAINT FK_T_Room_T_Client FOREIGN KEY(RM_CLI_ID)
REFERENCES dbo.T_Client (CLI_ID) 
ON DELETE CASCADE 

이제 당신은 말할 수 있습니다.

DELETE FROM T_Client WHERE CLI_ID = x 

클라이언트가 삭제되면 방이 자동으로 삭제됩니다.
문제 해결 - 애플리케이션 코드가 변경되지 않았습니다.

주의 사항 : Microsoft SQL-Server에서는 자체를 참조하는 테이블이 있으면이 기능이 작동하지 않습니다. 따라서 재귀 트리 구조에서 삭제 캐스케이드를 정의하려고하면 다음과 같이됩니다.

IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_T_FMS_Navigation_T_FMS_Navigation]') AND parent_object_id = OBJECT_ID(N'[dbo].[T_FMS_Navigation]'))
ALTER TABLE [dbo].[T_FMS_Navigation]  WITH CHECK ADD  CONSTRAINT [FK_T_FMS_Navigation_T_FMS_Navigation] FOREIGN KEY([NA_NA_UID])
REFERENCES [dbo].[T_FMS_Navigation] ([NA_UID]) 
ON DELETE CASCADE 
GO

IF  EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_T_FMS_Navigation_T_FMS_Navigation]') AND parent_object_id = OBJECT_ID(N'[dbo].[T_FMS_Navigation]'))
ALTER TABLE [dbo].[T_FMS_Navigation] CHECK CONSTRAINT [FK_T_FMS_Navigation_T_FMS_Navigation]
GO

Microsoft-SQL-server는 재귀 트리 구조에서 ON DELETE CASCADE 를 사용하여 외래 키를 설정할 수 없으므로 작동하지 않습니다. 그 이유 중 하나는 나무가 주기적으로 교착 상태에 빠질 가능성이 있기 때문입니다.

반면에 PostgreSQL은 이것을 할 수 있습니다.
요구 사항은 트리가 비순환 적이라는 것입니다.
트리가 순환하면 런타임 오류가 발생합니다.
이 경우 삭제 기능을 직접 구현해야합니다.

주의 사항 :
이것은 단순히 클라이언트 테이블을 삭제하고 다시 삽입 할 수 없다는 것을 의미합니다. 이렇게하면 "T_Room"...의 모든 항목이 삭제되기 때문입니다 (델타가 아닌 업데이트는 더 이상 필요하지 않습니다)



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow