2013-01-23 2 views
2

현재 트리 구조와 같은 DB에서 작업하고 있습니다. 기본적으로 최상위 테이블이 하나 있으며 그 테이블에 외래 키가있는 약 10 개의 테이블이 있습니다. 이 테이블 각각에는 외래 키 제약 조건이있는 또 다른 10 개의 테이블이 있습니다. 이제 내 목표는 메인 테이블에서 일부 레코드를 삭제하고 자식, 손자 등을 삭제하는 것입니다. 물론 외래 키를 사용하면이 작업이 까다로워집니다.외래 키가 많은 테이블에서 삭제

조금만 검색하여 캐스케이드 삭제를 사용하여이 question을 확인했는데 몇 가지 테이블 만 다루는 경우이 트릭을 수행 할 것입니다. 그러나, 현재 나의 설정에서 100 개 이상의 테이블을 하나씩 변경하는 것은 여전히 ​​즐겁지 않을 것입니다.

따라서 많은 테이블이 관련되어있을 때 외래 키가있는 값을 삭제하는 쉬운 방법이 있는지 묻습니다.

비교적 작은 DB를 제어 할 수 있기 때문에 쿼리 효율성과 다른 사람들이 값을 삭제할 위험이 없습니다. 따라서 모든 테이블에서 계단식 삭제를 적용하기는 쉽지만 Microsoft SQL Server 2008의 T-SQL 사용과는 완전히 다른 솔루션을 사용할 수 있습니다.

+0

부모 레코드를 삭제하더라도 * 기록 유지 * 목적으로이 값을 어린이에게 보관 하시겠습니까? – bonCodigo

+0

@bonCodigo 아니요 저는 아이들을 정말로 삭제하고 싶습니다. –

답변

1

삭제 캐스케이드는 "기본"테이블에 대한 좋은 해결책이 될 것입니다.

모든 테이블을 수동으로 변경하지 않으려면 here과 약간의 변경 (마지막 줄, 테이블 이름으로 <yourTable> 변경)이있는 스크립트를 사용할 수 있습니다.

select 
    DropStmt = 'ALTER TABLE [' + ForeignKeys.ForeignTableSchema + 
     '].[' + ForeignKeys.ForeignTableName + 
     '] DROP CONSTRAINT [' + ForeignKeys.ForeignKeyName + ']; ' 
, CreateStmt = 'ALTER TABLE [' + ForeignKeys.ForeignTableSchema + 
     '].[' + ForeignKeys.ForeignTableName + 
     '] WITH CHECK ADD CONSTRAINT [' + ForeignKeys.ForeignKeyName + 
     '] FOREIGN KEY([' + ForeignKeys.ForeignTableColumn + 
     ']) REFERENCES [' + schema_name(sys.objects.schema_id) + '].[' + 
    sys.objects.[name] + ']([' + 
    sys.columns.[name] + ']) ON DELETE CASCADE; ' 
from sys.objects 
    inner join sys.columns 
    on (sys.columns.[object_id] = sys.objects.[object_id]) 
    inner join (
    select sys.foreign_keys.[name] as ForeignKeyName 
    ,schema_name(sys.objects.schema_id) as ForeignTableSchema 
    ,sys.objects.[name] as ForeignTableName 
    ,sys.columns.[name] as ForeignTableColumn 
    ,sys.foreign_keys.referenced_object_id as referenced_object_id 
    ,sys.foreign_key_columns.referenced_column_id as referenced_column_id 
    from sys.foreign_keys 
     inner join sys.foreign_key_columns 
     on (sys.foreign_key_columns.constraint_object_id 
      = sys.foreign_keys.[object_id]) 
     inner join sys.objects 
     on (sys.objects.[object_id] 
      = sys.foreign_keys.parent_object_id) 
     inner join sys.columns 
      on (sys.columns.[object_id] 
      = sys.objects.[object_id]) 
      and (sys.columns.column_id 
      = sys.foreign_key_columns.parent_column_id) 
    ) ForeignKeys 
    on (ForeignKeys.referenced_object_id = sys.objects.[object_id]) 
    and (ForeignKeys.referenced_column_id = sys.columns.column_id) 
where (sys.objects.[type] = 'U') 
    and (sys.objects.[name] = '<yourTable>') 

당신은 다음 두 번째 열이 동일 할, 봐라, 당신은 완료, 실행하는 관리 Studio 쿼리 창에서 첫 번째 열 결과를 복사합니다.

+0

'yourtable'을 테이블 이름으로 대체해야한다는 것을 알고 있습니다. 하지만 필드 'IsActive = 0'에서 레코드를 제거하고 싶다는 것을 어떻게 나타낼 수 있습니까? 어떻게 외래 키를 원래 상태로 설정합니까? –

+0

@DennisJaheruddin이 버전은 "IsActive = 0"이 아닙니다. 캐스케이드 삭제를 가능하게하는 버전입니다. 그래서 레코드가 삭제 될 것입니다 ("IsActive"에 대한 질문이 없기 때문에 외래 키를 원래 상태로 되돌려 놓는 것이 아닙니다. 그러나 원하는 경우 스크립트를 다시 작성하고 "ON DELETE CASCADE" 부분. –

+0

감사합니다. 외래 키를 복원하는 것은 간단합니다. 그렇다면 스크립트가 실제로 아무것도 삭제하지는 않지만 올바르게 처리 할 수 ​​있다는 것을 정확히 이해합니까? 이후에 항목을 직접 삭제할 수 있습니까? –

1

다른 방법으로 이런 식으로하는 가장 좋은 방법은 논리 삭제를 사용하여 "상태"라는 열 또는 해당 필드가 여전히 프로그램 논리 아래에서 고려되는지 제어하는 ​​것입니다. . 상태 열은 최상위 테이블에서만 만들어야합니다. SQL 문에서 "where status = 1"또는 이와 유사한 것을 삽입합니다.

도움이되는 희망은 질문에 대한 완전히 다른 접근 방식이기 때문에 도움이됩니다.

+0

이것은 논리적으로 삭제 된 열을 설명하기 위해 앱에있는 모든 쿼리를 변경한다는 의미입니다. 계단식 삭제는 훨씬 저렴할 것입니다. – Farzad

+0

이것을 이해하고 있다고 생각하지만,이 값을 추적하기 위해 조인을 작성해야한다는 것을 의미하는 경우 유용한 솔루션으로 보이지 않습니다. –

+0

비싸다. 그래도 좋은 생각. –

2

본 적이 있습니까? 이 사람은 데이터베이스에있는 외래 키 관계에 따라 삭제 문을 자동 생성된다

Generate Delete Statement From Foreign Key Relationships in SQL 2008?

나는 그것의 큰 팬이 개인적으로 모르지만 그것을 시도하는 일이다.

+0

'MyTableName'을 테이블 이름으로 대체해야한다는 것을 알고 있지만 'IsActive = 0'필드가있는 레코드를 제거하려면 어떻게해야합니까? 내가 끝난 후에 db가 다시 '안전'한 것을 확인하기 위해 무엇이든해야합니까? –

-1

참조한 질문에서 언급했듯이 ON DELETE CASCADE을 사용하여 자동으로 삭제를 처리 할 수 ​​있습니다.

+0

그러나 어떻게하면 수많은 테이블을 방문하지 않고도 (그리고 나중에 더 추가 될 수 있습니다) 이자형? –

+0

변경 스크립트는 충분히 쉽습니다. 이제 약간의 데이터베이스 관리가 먼 길을 간다. 대안은 1) 상위 테이블의 키로 기본 테이블의 정보를 먼저 삭제 한 다음 상위 테이블의 정보를 삭제하십시오. 2) 다른 응답에서 제안 된대로 삭제 플래그를 사용하십시오. 둘 다 내 제안보다 유지하기가 더 어렵거나 비싸다. –

0

데이터 무결성을 희생하지 않으려면 T_SQL CASCADE DELETE 옵션을 사용하십시오. "ALTER TABLE PARENT1 FOREIGN KEY"를 작성하여 안전하게 솔루션에 복사하여 붙여 넣을 수 있습니다.

프로그래밍 방식 솔루션을 개발하고 테스트하는 것보다 시간이 훨씬 적게 소요됩니다.이 프로그램은 Mgmt와 같은 타사 프로그램을 통해 delete 문을 실행하면 실행되지 않습니다. 사진관.

관련 문제