sourcecode

데이터베이스에서 상속을 어떻게 표현할 수 있습니까?

copyscript 2023. 5. 24. 22:19
반응형

데이터베이스에서 상속을 어떻게 표현할 수 있습니까?

SQL Server 데이터베이스에서 복잡한 구조를 어떻게 표현할지 고민 중입니다.

개체 패밀리의 세부 정보를 저장해야 하는 애플리케이션을 예로 들어 보겠습니다. 이러한 애플리케이션은 일부 속성은 공유하지만 다른 속성은 일반적이지 않습니다.예를 들어, 상업 보험 패키지에는 동일한 보험 기록 내의 책임, 자동차, 재산 및 보상 보험이 포함될 수 있습니다.

섹션 컬렉션을 사용하여 정책을 생성할 수 있으므로 C# 등에서 이를 구현하는 것은 사소한 일입니다. 섹션은 다양한 유형의 커버에 대해 필요에 따라 상속됩니다.그러나 관계형 데이터베이스는 이를 쉽게 허용하지 않는 것 같습니다.

두 가지 주요 선택지가 있다는 것을 알 수 있습니다.

  1. 가능한 모든 변형에 대해 필요한 모든 필드가 포함된 정책 테이블을 만든 다음 섹션 테이블을 만듭니다. 대부분은 null입니다.

  2. 정책 테이블과 여러 개의 섹션 테이블을 만듭니다(각 커버 유형에 대해 하나씩).

특히 모든 섹션에 걸쳐 수많은 조인 또는 수많은 null-check를 포함하는 쿼리를 작성해야 하기 때문에 이러한 두 가지 대안 모두 만족스럽지 못한 것으로 보입니다.

이 시나리오에 가장 적합한 방법은 무엇입니까?

@Bill KarwinSQL Entity-Attribute-Value 반대 패턴에 대한 솔루션을 제안할 때 SQL Antipatterns 책에서 세 가지 상속 모델을 설명합니다.다음은 간략한 개요입니다.

단일 테이블 상속(계층별 테이블 상속):

첫 번째 옵션과 같이 단일 테이블을 사용하는 것이 가장 단순한 설계입니다.에 특화된 신 유 특 에 형 속 많 정 한 은 다 성 것 같 니 다 입 할 주 야 져 어 이 음 과 위 은 이 급 듯 했 ▁a ▁have ▁attrib utes ▁as ▁that ▁given 다 ▁toNULL이러한 속성이 적용되지 않는 행의 값입니다.모델을 테이블이 .

+------+---------------------+----------+----------------+------------------+
| id   | date_issued         | type     | vehicle_reg_no | property_address |
+------+---------------------+----------+----------------+------------------+
|    1 | 2010-08-20 12:00:00 | MOTOR    | 01-A-04004     | NULL             |
|    2 | 2010-08-20 13:00:00 | MOTOR    | 02-B-01010     | NULL             |
|    3 | 2010-08-20 14:00:00 | PROPERTY | NULL           | Oxford Street    |
|    4 | 2010-08-20 15:00:00 | MOTOR    | 03-C-02020     | NULL             |
+------+---------------------+----------+----------------+------------------+

\------ COMMON FIELDS -------/          \----- SUBTYPE SPECIFIC FIELDS -----/

설계를 단순하게 유지하는 것은 장점이지만, 이 접근 방식의 주요 문제는 다음과 같습니다.

  • 새 하위 유형을 추가할 때는 이러한 새 개체를 설명하는 특성을 수용하도록 테이블을 변경해야 합니다.하위 유형이 많거나 하위 유형을 정기적으로 추가하려는 경우 이 문제가 빠르게 발생할 수 있습니다.

  • 어떤 속성이 어떤 하위 유형에 속하는지 정의할 메타데이터가 없기 때문에 데이터베이스는 어떤 속성이 적용되고 어떤 속성이 적용되지 않는지를 적용할 수 없습니다.

  • 또적할수없다니습한을 강제로 시행할 수 .NOT NULL필수 항목이어야 하는 하위 유형의 속성에 대해 설명합니다.일반적으로 이상적이지 않은 애플리케이션에서 이 문제를 처리해야 합니다.

콘크리트 테이블 상속:

상속 문제를 해결하는 또 다른 방법은 각 하위 유형에 대해 새 테이블을 만들어 각 테이블의 모든 공통 속성을 반복하는 것입니다.예:

--// Table: policies_motor
+------+---------------------+----------------+
| id   | date_issued         | vehicle_reg_no |
+------+---------------------+----------------+
|    1 | 2010-08-20 12:00:00 | 01-A-04004     |
|    2 | 2010-08-20 13:00:00 | 02-B-01010     |
|    3 | 2010-08-20 15:00:00 | 03-C-02020     |
+------+---------------------+----------------+
                          
--// Table: policies_property    
+------+---------------------+------------------+
| id   | date_issued         | property_address |
+------+---------------------+------------------+
|    1 | 2010-08-20 14:00:00 | Oxford Street    |   
+------+---------------------+------------------+

이 설계는 기본적으로 단일 테이블 방법에 대해 식별된 문제를 해결합니다.

  • 이제 은 이제필사속적수있습다니용할로 적용할 수.NOT NULL.

  • 새 하위 유형을 추가하려면 기존 테이블에 열을 추가하는 대신 새 테이블을 추가해야 합니다.

  • 또한 다음과 같은 특정 하위 유형에 대해 부적절한 속성이 설정될 위험도 없습니다.vehicle_reg_no속성 정책의 필드입니다.

  • 다음이 필요하지 않습니다.type단일 테이블 방법에서와 같은 속성.이제 유형은 메타데이터, 즉 테이블 이름으로 정의됩니다.

그러나 이 모델에는 다음과 같은 몇 가지 단점도 마찬가지입니다.

  • 공통 속성은 하위 유형의 특정 속성과 혼합되어 있으며, 이를 쉽게 식별할 수 있는 방법이 없습니다.데이터베이스도 알 수 없습니다.

  • 테이블을 정의할 때는 각 하위 유형 테이블에 대해 공통 속성을 반복해야 합니다.그건 절대 드라이가 아닙니다.

  • .UNIONs의

다음은 유형에 관계없이 모든 정책을 쿼리하는 방법입니다.

SELECT     date_issued, other_common_fields, 'MOTOR' AS type
FROM       policies_motor
UNION ALL
SELECT     date_issued, other_common_fields, 'PROPERTY' AS type
FROM       policies_property;

.UNION ALL 경우 할 수 있습니다.이 작업을 잊어버린 경우 응용 프로그램에 버그가 발생할 수 있습니다.

클래스 테이블 상속(유형별 테이블 상속):

이것은 @David가 다른 대답에서 언급한 해결책입니다.모든 공통 속성을 포함하는 기본 클래스에 대한 단일 테이블을 만듭니다.그런 다음 기본 키가 기본 테이블에 대한 외부 키 역할도 하는 각 하위 유형에 대한 특정 테이블을 만듭니다.예:

CREATE TABLE policies (
   policy_id          int,
   date_issued        datetime,

   -- // other common attributes ...
);

CREATE TABLE policy_motor (
    policy_id         int,
    vehicle_reg_no    varchar(20),

   -- // other attributes specific to motor insurance ...

   FOREIGN KEY (policy_id) REFERENCES policies (policy_id)
);

CREATE TABLE policy_property (
    policy_id         int,
    property_address  varchar(20),

   -- // other attributes specific to property insurance ...

   FOREIGN KEY (policy_id) REFERENCES policies (policy_id)
);

이 솔루션은 다른 두 설계에서 확인된 문제를 해결합니다.

  • 필수 속성은 다음을 사용하여 적용할 수 있습니다.NOT NULL.

  • 새 하위 유형을 추가하려면 기존 테이블에 열을 추가하는 대신 새 테이블을 추가해야 합니다.

  • 특정 하위 유형에 대해 부적절한 특성이 설정될 위험이 없습니다.

  • 필요 없음type기여하다.

  • 이제 공통 속성은 더 이상 하위 유형의 특정 속성과 혼합되지 않습니다.

  • 우리는 마침내 건조함을 유지할 수 있습니다.테이블을 만들 때 각 하위 유형 테이블에 대해 공통 속성을 반복할 필요가 없습니다.

  • 자동 증분 관리id각 하위 유형 테이블이 정책을 독립적으로 생성하는 대신 기본 테이블에서 정책을 처리할 수 있기 때문에 정책이 더 쉬워집니다.

  • 이제 하위 유형에 관계없이 모든 정책을 쉽게 검색할 수 있습니다.아니요.UNION필요 - 그냥SELECT * FROM policies.

저는 대부분의 상황에서 가장 적합한 것이 수업 테이블 접근법이라고 생각합니다.


이 세 가지 모델의 이름은 Martin Fowler의 엔터프라이즈 응용프로그램 아키텍처 패턴에서 따왔습니다.

세 번째 선택사항은 "정책" 테이블을 작성한 후 섹션 유형에서 공통되는 모든 필드를 저장하는 "섹션 기본" 테이블을 작성하는 것입니다.그런 다음 각 섹션 유형에 대해 공통되지 않은 필드만 포함하는 다른 테이블을 작성합니다.

어떤 것이 최선인지 결정하는 것은 대부분 얼마나 많은 필드를 가지고 있고 어떻게 SQL을 작성할 것인지에 달려 있습니다.그들은 모두 일을 할 것입니다.만약 당신이 몇 개의 필드만 있다면 저는 아마 1번으로 갈 것입니다."많은" 분야에서 저는 #2 또는 #3으로 기울었습니다.

Daniel Vassallo 솔루션 외에도 SQL Server 2016+를 사용하는 경우 성능이 크게 저하되지 않는 다른 솔루션이 있습니다.

공통 필드만 있는 테이블을 만들고 모든 하위 유형 특정 필드가 포함된 JSON 문자열을 사용하여 단일 열을 추가하면 됩니다.

상속 관리를 위해 이 설계를 테스트했으며 관련 응용프로그램에서 사용할 수 있는 유연성에 매우 만족합니다.

제공된 정보를 사용하여 데이터베이스를 다음과 같이 모델링합니다.

정책들

  • POLICY_ID(기본 키)

부채

  • 책임_ID(기본 키)
  • POLICY_ID(외래 키)

특성.

  • PROPERY_ID(기본 키)
  • POLICY_ID(외래 키)

...정책의 각 섹션과 관련된 다양한 특성이 있을 것으로 예상되기 때문입니다.그렇지 않으면, 단 한 명의 사람이SECTIONSpolicy_id있을 것입니다.section_type_code...

어느 쪽이든 정책별로 선택적 섹션을 지원할 수 있습니다.

이 접근 방식에 대해 만족스럽지 못한 점을 이해할 수 없습니다. 이렇게 하면 데이터를 중복하지 않고 참조 무결성을 유지하면서 데이터를 저장할 수 있습니다.용어는 "정상화된"...

SQL은 SET 기반이기 때문에 절차/OO 프로그래밍 개념에 다소 생소하며 한 영역에서 다른 영역으로 전환하기 위해 코드가 필요합니다.ORM은 종종 고려되지만 대량의 복잡한 시스템에서는 제대로 작동하지 않습니다.

그을하또다방법은른것입, 사는하다니용는것▁the다것을 사용하는 것입니다.INHERITS를 들어 다음과 같습니다예:

CREATE TABLE person (
    id int ,
    name varchar(20),
    CONSTRAINT pessoa_pkey PRIMARY KEY (id)
);

CREATE TABLE natural_person (
    social_security_number varchar(11),
    CONSTRAINT pessoaf_pkey PRIMARY KEY (id)
) INHERITS (person);


CREATE TABLE juridical_person (
    tin_number varchar(14),
    CONSTRAINT pessoaj_pkey PRIMARY KEY (id)
) INHERITS (person);

따라서 테이블 간의 상속을 정의할 수 있습니다.

또는 풍부한 데이터 구조와 중첩을 기본적으로 지원하는 문서 데이터베이스(예: MongoDB)를 사용하는 것을 고려하십시오.

저는 전체 정책을 모든 섹션과 함께 효율적으로 검색하기 위해 방법 #1(통합 섹션 표)을 선호합니다(시스템에서 많은 작업을 수행할 것으로 예상됨).

또한 사용 중인 SQL Server 버전이 무엇인지 모르지만 2008년에는 열에 있는 많은 값이 NULL인 상황에서 성능을 최적화하는 데 도움이 됩니다.

궁극적으로 정책 섹션이 얼마나 "유사한지" 결정해야 합니다.그들이 크게 다르지 않은 한, 더 정상화된 해결책은 가치보다 더 큰 문제가 될 수도 있다고 생각합니다.하지만 당신만이 그 전화를 할 수 있습니다.:)

언급URL : https://stackoverflow.com/questions/3579079/how-can-you-represent-inheritance-in-a-database

반응형