2011-09-23 5 views
1

나는 다음과 같은 테이블이 있습니다 이 표는 group_systems CREATE ( GROUP_NAME, 여기서 system_name, SECTION_NAME, CREATED_DATE, decom_date, 상태 (활성, 비활성화) )구현하는 복잡한 점검 제한 조건

CREATE TABLE 시스템 ( system_name, section_name )

시스템 키 (system_name, section_name)로 식별됩니다. dup 시스템 이름은있을 수 있지만 dup 섹션 이름은 없을 수 있습니다.

그룹 테이블에서 그룹의 섹션에있는 하나의 시스템 만 활성화 될 수 있다는 제약 조건을 적용하고 싶습니다. 그러나 그룹 테이블은 히스토리 테이블이기 때문에 고유 제한 조건 (group_name, section_name, system_name) 만 사용할 수는 없습니다. 하위 쿼리를 실행하는 check 제약 조건을 사용해야합니다. 하위 쿼리 인 몇 가지 추가 제약 조건이 있습니다.

문제는 100k 레코드의 벤치 마크 삽입에는 (서브 쿼리로 인해) 시간이 오래 걸린다는 것입니다.

group_systems 테이블을 다시 참조하는 다른 테이블 active_systems_for_groups를 빌드하는 것이 더 좋습니까? 그렇게하면 그룹 당 섹션 당 하나의 활성 시스템 만 적용하고 더 많은 테이블을 추가하여 복잡한 제약 조건을 유지하는 active_systems_for_groups에 고유 제한 조건을 추가 할 수 있습니다.

복잡한 체크 제약 조건을 처리하는 더 좋은 방법이 있습니까?

+0

어떤 RDBMS를 사용하고 있습니까? –

+0

서브 쿼리를 지원하는'CHECK' 제약 조건을 가진 SQL 구현을 사용하고 있습니까? 내가 아는 유일한 것은 Access (ACE, Jet, 무엇이든)이며 SQL Server가 UDF를 사용하여 '가짜'로 만들 수 있다는 것을 알고 있습니다. 그것이 다른 것이라면, 나는 그것이 어떤 SQL인지 배우게 될 것이다. Firebird (귀하의 손에 의해 제안 된 바와 같이) AFAIK하지 않습니다. – onedaywhen

답변

2
당신은 두 가지 방법으로 "하나의 활동 기록"패턴을 적용 할 수 있습니다

:

  1. 여러에서 활성 레코드의 기본 키 값을 유지하는 테이블을 만드는 것입니다 당신이 제안 솔루션, -records-allowed 테이블. 이러한 값은 활성 레코드 테이블의 기본 키 역할을합니다.

  2. 각각 하나의 활성 레코드 만 가질 수있는 오브젝트를 나타내는 다른 테이블에 컬럼을 추가합니다. 이 경우 시스템에 컬럼 active_group_name을 추가하는 것입니다. 이 열은 다중 레코드가 허용 된 테이블에 대한 외래 키입니다. 바람직

모든 섹션 그것이 여부, 활성 그룹을 갖는 요구인지 여부에 부분적으로 의존 공통 여부 활성 그룹이 있거나하는 섹션 (하지만 필수) 섹션에 활성 그룹이있는 경우가 종종 있습니다.

첫 번째 경우 (필수)에서는 옵션 (2)을 사용하고 열은 완전한 정규화를 유지하면서 NOT NULL로 선언 될 수 있습니다. 두 번째 경우 (common)에서는 열을 NULL로 만들 필요가 있지만 JOIN의 편의를 위해이 기술을 사용합니다. 세 번째 경우 (가끔)에서는 활성 레코드를 얻기 위해 조인 할 때 성능을 향상시킬 수 있으므로 옵션 (1)을 사용합니다.

+0

"첫 번째 경우 (필수)에서 옵션 (2)을 사용하면 열이 완전한 정규화를 유지하면서 NOT NULL로 선언 될 수 있습니다."- 열을 선언하는 것 (열 - hint = "히스토리 테이블")을 nullable로 지정하면 비정규 화가 발생합니다. 두 가지 경우에 대해 어느 표 형식이 될 것이라고 생각하십니까? 힌트 : 이것은 비정규 화를 의미하지 않는다고 생각하지만 증명의 부담은 당신에게있다. – onedaywhen

+0

나는 정규식에 관한 논점 인 "핀의 머리에있는 천사"에 실제로 있지는 않지만 많은 사람들이 NULLable 열이 * 1 * 정상 형식을 위반한다고 생각합니다. 대부분 학문적 주장이라고 생각하지만 많은 사람들이 그것을합니다. –

+0

확실하지만 그 대답은 당신이 의미하는 바가 아닙니다. 맞습니까? 그래서 무슨 뜻이야? 의미가 없으면 그냥 제거하십시오. 여기에 논쟁 없음 :) – onedaywhen

1

당신이 사용하고있는 RDBMS에 대한 답을 얻지 못했기 때문에 SQL Server (2008 또는 이후 버전)에서이 제약 조건을 쉽게 처리 할 수있는 다른 방법에 관심이있는 다른 사람들을 위해이 목록을 게시 할 것입니다.

필터 된 고유 색인을 사용하여 주어진 유형의 "활성"행 수에 제한 조건을 효과적으로 적용 할 수 있습니다.

CREATE UNIQUE INDEX My_Table_active_IDX ON My_Table (some_pk) WHERE active = 1 

이 방법이 여러 가지 장점 : 예를 들어

  1. 그것은 자기 포함 된 단일 테이블 내에서의 (더 FKS이, 당신이 필요로하는 다른 객체가 업데이트되지 계속 선언적이다 등)
+0

나는이 해결책이 다른 것보다 실제로 악하다고 생각합니다. 왜냐하면 1) 활성 레코드를 변경하는 데 두 번의 UPDATE가 필요하기 때문입니다. 2) 추가 색인이 필요합니다 3) 동일한 데이텀이 두 번 이상 저장됩니다 .4) 'NULL'이 허용되며, 필수 항목이며, 5) 정보가 잘못된 위치에 저장됩니다 (활성 레코드는 다음과 같습니다. 소유자의 속성이지 레코드 자체는 아닙니다. 또한, 내가 한 제안은 모두 선언적입니다. –

+1

어?!?! 당신이 설명하는 mthods는 추가 업데이 트가 필요합니다. 여기에는 아무 것도 필요 없습니다. 데이터는 두 번 이상 저장되지 않습니다. 인덱스 유지 관리는 거의 항상 거의 무시할 수 있으며 확실히 "활성"행을 추적하는 추가 테이블을 유지하는 것보다 적습니다. 전혀 NULL을 필요로하지 않습니다. 두 솔루션 모두 추가 테이블이 필요합니다. 나는 당신이 여기서 뭔가 잘못 이해했다고 생각합니다. –

+0

전혀 아닙니다. 내 솔루션에는 ** ** IsActive 필드가 없습니다 ** UPDATE. 필요한 유일한 * UPDATE는 선택된 방법에 따라'system_active_groups' 테이블의'systems' 테이블에서 하나의 레코드에 대한 레코드입니다 (두 솔루션 중 하나에서 INSERT 또는 UPDATE). 'IsActive' 필드를 유지한다면, 두 개의 레코드를'UPDATE'해야합니다. 비활성 상태는 비활성 상태 인 레코드와 활성 상태 인 레코드의 두 번째 상태 모두에 보유되기 때문에 데이터 *는 두 번 이상 저장됩니다. 그러나 두 번째 저장소에 대해 'NULL'대신 0을 사용할 수 있습니다. –