2017-10-19 6 views
0

이것은 꼬임이 있지만 (즉, 기본적으로 여기에 참조 횟수 동작이 필요합니다) this question과 비슷합니다.역방향 외부 키 캐스 캐이 딩 (또는 데이터베이스 쓰레기 수거 방법)

우리는 여러 가지 테이블 (Foo, Bar, Baz)을 가지고 있습니다. 여기에 저장된 것들은 모두 0 가지 이상의 다른 종류의 (Blah)를 참조합니다. 때때로 새로운 Blah를 만들어 Foo, Bar 또는 Baz에 첨부합니다. 그러나, 우리는 한 번에 여러 가지로 지적 될 수있는 기존의 Blah를 편집하지 않습니다. 현재 데이터베이스의 모든 Foos, Bars, Bazes를 스윕하고, 사용 된 Blahs를 표시 한 다음, 표시되지 않은 모든 Blah를 삭제하는 일괄 처리를 수행합니다. 그러나 이것은 비용이 많이 드는 일이므로, 수행 할 방법을 찾고 있습니다. 온라인으로, 이상적으로는 데이터베이스 자체를 통해. 방아쇠 기반 접근법을 연구 할 수는 있지만 최후의 수단으로 치료하려고합니다.

  • 나는 새로운 바 'some_bar'를 삽입하고 PK 'R'만 이미 고아 ㅋ로 새로운 어쩌구에 그것을 지점이있는 경우 : this SQLFiddle의 스키마 및 데이터를 참조 특히

    , 'x'는 삭제해야합니다.

  • 'a_foo'를 삭제하면 'blahs'a '와'x '만 삭제해야합니다. 특히'b '와'c '는 그대로 두어야합니다.
  • 'another_foo ' 내가 'another_bar을 삭제하면
  • 을 유지하기 위해 특정 요구에 ㅋ'C를 '- Blahs'X '와'Y '
  • 내가'a_bar '를 삭제하면
  • 이 만 ㅋ'X '가 삭제 될 수 있습니다 삭제해야 ', blah'q '만 지워야합니다.
  • 'a_baz '를 삭제하면'blahs 'p', 'x'및 'z'가 모두 삭제되어야합니다. 삭제됨
  • 'another_baz'를 삭제하면 'blah'x '만 삭제할 수 있습니다. 삭제됨 - Blahs 'b'및 'q'가 주위에 있어야 함

이 작업에 대해 트리거 또는 기존 마크 스윕 일괄 처리를 사용하고 있습니까? 아니면 더 나은 방법이 있습니까? 한 BLAHS.PK 쉼표를 포함하지 않을 수있는 일을 할 것입니다 다음 쿼리 이후 마크 스윕 일괄 처리에 대한 필요가 없습니다

답변

1

: 당신이 어떤을 정의 할 수 없기 때문에

delete from blahs 
where not exists (select 1 from foo where ','||some_blahs||',' like '%,'||blahs.pk||',%') 
    and not exists (select 1 from bar where bar.blah = blahs.pk) 
    and not exists (select 1 from baz where blahs.pk in (baz.a_blah, baz.another_blah)); 

테이블 FOO이 문제가된다 참조 무결성 또는 BARBAZ과 같은 유용한 인덱스를 사용할 수 있습니다. 대신 다음

create table foo_blahs (foo_pk varchar2(20) references foo on delete cascade 
         , blah_pk varchar2(20) references blahs 
         , constraint foo_blah_pk primary key (foo_pk, blah_pk) enable); 

:

insert into foo (pk, some_blahs) values ('a_foo', 'a,b,c'); 

당신은 사용합니다 :

insert into foo (pk) values ('a_foo'); 
insert into foo_blahs (foo_pk, blah_pk) values ('a_foo', 'a'); 
insert into foo_blahs (foo_pk, blah_pk) values ('a_foo', 'b'); 
insert into foo_blahs (foo_pk, blah_pk) values ('a_foo', 'c'); 

더 나은 DB 설계는 많은 관계 테이블에 많은으로 FOO.SOME_BLAHS을 대체 할 수 있습니다 삭제 쿼리는

이됩니다.210
delete from blahs 
where not exists (select 1 from foo_blahs where foo_blahs.blah_pk = blahs.pk) 
    and not exists (select 1 from bar where bar.blah = blahs.pk) 
    and not exists (select 1 from baz where blahs.pk in (baz.a_blah, baz.another_blah)); 
+0

그래,'foo'의 "외래 키"설정은 내 생각이 아니 었습니다.하지만 당신은 플랫 파일 랜드에서 설계된 데이터를 다루기 위해해야 ​​할 일을합니다. 나 자신에게 다 대다 테이블을 가지고있다. 그러나 그것은 슬픈 듯이 다른 곳에서 특별한 케이싱 문제를 만든다. – LThode

+0

아, 네가해야할 일을 잘 해내 라. 다 대다 표현을 할 수 있다면 blahs에 errologging 테이블을 추가 할 수 있습니다. 'EXECUTE DBMS_ERRLOG.CREATE_ERROR_LOG ('blahs ','errlog '); 그러면 blahs 로그 오류를 errlog (' doh ') reject limit unlimited;'이며 참조 무결성은 참조 된 blah가 삭제되지 않게합니다. errlog 테이블을 전역 임시 테이블로 만들면 주기적으로 정리할 필요가 없습니다. – Sentinel

+0

첫 번째 쿼리에 대해서는 기본 구조가 작동했지만 WHERE 절이 오 탐지 (false positive)의 방대한 생성기로 밝혀졌습니다. 나는 그것을 INSTR의 응용 프로그램으로 바꿨다. 나는 그것이 LIKE만큼 성능이 좋다고 생각하지 않지만 적어도 정확한 레코드 세트를 반환한다. – LThode