문제

다양한 차량의 충돌 테스트 데이터를 저장하기 위해 데이터베이스를 설정하고 있다고 가정합니다. 스피드 보트, 자동차 및 고 카트에 대한 충돌 테스트 데이터를 저장하려고합니다.

Speedboattests, Cartests 및 GokartTest의 세 가지 별도 테이블을 만들 수 있습니다. 그러나 많은 열이 각 테이블에서 동일합니다 (예 : 테스트를 수행 한 사람의 직원 ID, 충돌 방향 (전면, 측면, 후면) 등). 그러나 많은 열이 다를 수 있으므로 모든 테스트 데이터를 단일 테이블에 넣고 싶지는 않습니다. 자동차를 위해 무효가되고, 항상 go-karts의 경우에는 꽤 많은 것들이 있습니다.

또한 테스트와 직접 관련이없는 정보 (예 : 테스트중인 물건의 디자이너의 직원 ID)를 저장하고 싶다고 가정 해 봅시다. 이 열은 "테스트"테이블을 전혀 넣는 것이 옳지 않은 것처럼 보이며, 특히 동일한 차량의 모든 테스트에 대해 반복되기 때문입니다.

테이블의 가능한 한 가지 배열을 설명하겠습니다. 따라서 관련된 질문을 볼 수 있습니다.

Speedboats
id | col_about_speedboats_but_not_tests1 | col_about_speedboats_but_not_tests2

Cars
id | col_about_cars_but_not_tests1 | col_about_cars_but_not_tests2

Gokarts
id | col_about_gokarts_but_not_tests1 | col_about_gokarts_but_not_tests2

Tests
id | type | id_in_type | col_about_all_tests1 | col_about_all_tests2
(id_in_type will refer to the id column of one of the next three tables,
depending on the value of type)

SpeedboatTests
id | speedboat_id | col_about_speedboat_tests1 | col_about_speedboat_tests2

CarTests
id | car_id | col_about_car_tests1 | col_about_car_tests2

GokartTests
id | gokart_id | col_about_gokart_tests1 | col_about_gokart_tests2

이 구조에 대한 좋은/나쁜 점은 무엇이며 이와 같은 것을 구현하는 선호하는 방법은 무엇입니까?

차량 테이블에 갖고 싶은 모든 차량에 적용되는 정보도 있다면 어떨까요? Cartests 테이블이 ...

id | vehicle_id | ...

With a Vehicles table like this:
id | type | id_in_type
(with id_in_type pointing to the id of either a speedboat, car, or go-kart)

이것은 단지 왕의 혼란이되는 것입니다. 이와 같은 것을 어떻게 설정해야합니까?

도움이 되었습니까?

해결책

그만큼 type 그리고 id_in_type 디자인이 호출됩니다 다형성 연관성. 이 설계는 여러 가지 방식으로 정규화 규칙을 중단합니다. 다른 것이 없다면, 그것은 당신이 붉은 깃발이어야합니다. 캔트 실제 외국의 주요 제약을 선언합니다 id_in_type 여러 테이블을 참조 할 수 있습니다.

테이블을 정의하는 더 나은 방법은 다음과 같습니다.

  • 추상 테이블을 만드십시오 Vehicles 모든 차량 하위 유형 및 차량 테스트에 대한 추상 참조 점을 제공합니다.
  • 각 차량 하위 유형에는 자동 증가가 아니라 대신 참조가있는 기본 키가 있습니다. Vehicles.
  • 각 테스트 하위 유형에는 자동 증가하지 않고 대신 참조가있는 기본 키가 있습니다. Tests.
  • 각 테스트 하위 유형에는 해당 차량 하위 유형에 대한 외국 키가 있습니다.

샘플 DDL은 다음과 같습니다.

CREATE TABLE Vehicles (
 vehicle_id INT AUTO_INCREMENT PRIMARY KEY
);

CREATE TABLE Speedboats (
 vehicle_id INT PRIMARY KEY,
 col_about_speedboats_but_not_tests1 INT,
 col_about_speedboats_but_not_tests2 INT,
 FOREIGN KEY(vehicle_id) REFERENCES Vehicles(vehicle_id)
);

CREATE TABLE Cars (
 vehicle_id INT PRIMARY KEY,
 col_about_cars_but_not_tests1 INT,
 col_about_cars_but_not_tests2 INT,
 FOREIGN KEY(vehicle_id) REFERENCES Vehicles(vehicle_id)
);

CREATE TABLE Gokarts (
 vehicle_id INT PRIMARY KEY,
 col_about_gokarts_but_not_tests1 INT,
 col_about_gokarts_but_not_tests2 INT,
 FOREIGN KEY(vehicle_id) REFERENCES Vehicles(vehicle_id)
);

CREATE TABLE Tests (
 test_id INT AUTO_INCREMENT PRIMARY KEY,
 col_about_all_tests1 INT,
 col_about_all_tests2 INT
);

CREATE TABLE SpeedboatTests (
 test_id INT PRIMARY KEY,
 vehicle_id INT NOT NULL,
 col_about_speedboat_tests1 INT,
 col_about_speedboat_tests2 INT,
 FOREIGN KEY(test_id) REFERENCES Tests(test_id),
 FOREIGN KEY(vehicle_id) REFERENCES Speedboats(vehicle_id)
);

CREATE TABLE CarTests (
 test_id INT PRIMARY KEY,
 vehicle_id INT NOT NULL,
 col_about_car_tests1 INT,
 col_about_car_tests2 INT,
 FOREIGN KEY(test_id) REFERENCES Tests(test_id),
 FOREIGN KEY(vehicle_id) REFERENCES Cars(vehicle_id)
);

CREATE TABLE GokartTests (
 test_id INT PRIMARY KEY,
 vehicle_id INT NOT NULL,
 col_about_gokart_tests1 INT,
 col_about_gokart_tests2 INT,
 FOREIGN KEY(test_id) REFERENCES Tests(test_id),
 FOREIGN KEY(vehicle_id) REFERENCES Gokarts(vehicle_id)
);

대안 적으로 선언 할 수 있습니다 Tests.vehicle_id 어떤 참조 Vehicles.vehicle_id 각 테스트 하위 유형 테이블에서 Vehicle_ID 외래 키를 제거하지만 Gokart의 ID를 참조하는 스피드 보트 테스트와 같은 이상이 허용됩니다.

다른 팁

상속 계층을 데이터베이스 테이블에 매핑하기 위해 Martin Fowler는 그의 책 패턴의 엔터프라이즈 애플리케이션 아키텍처에서 대안을 상당히 잘 설명한다고 생각합니다.

http://martinfowler.com/eaacatalog/singletableinheritance.html

http://martinfowler.com/eaacatalog/classtableinheritance.html

http://martinfowler.com/eaacatalog/concretetableinheritance.html

서브 클래스의 경우 추가 필드/열의 수가 작 으면 단일 테이블 상속이 일반적으로 가장 간단합니다.

데이터베이스에 PostgreSQL을 사용하고 있고 데이터베이스 별 기능에 자신을 기꺼이 묶으려면 테이블 상속을 직접 지원합니다.

http://www.postgresql.org/docs/8.3/static/ddl-inherit.html

나는 그것을 다른 테이블, 예를 들어 차량 (ID, 유형 등) vehicleattributes () Vehicle, Attribute, value), CrashTestInfo (Vehicle, CrashTestID, Date 등) CrashTestAttributes (CrashTestID, Attribute, Value)로 나눕니다.

또는 속성보다는 기록되어야하는 각 유사한 세부 사항 세트에 대한 별도의 테이블.

사용중인 경우 sqlalchemy, 파이썬의 객체 관계 맵퍼 상속 계층이 데이터베이스 테이블에 매핑되는 방법을 구성하십시오. 객체 관련 매퍼는 지루한 SQL을 길들이기에 좋습니다.

문제는 수직 테이블에 적합 할 수 있습니다. 스키마에 모든 것을 저장하는 대신 객체의 유형과 기본 키를 한 테이블에 저장하고 각 객체의 키/값 튜플을 다른 테이블에 저장하십시오. 자동차 테스트를 실제로 저장하고 있다면이 설정을 통해 새로운 종류의 결과를 더 쉽게 추가 할 수 있습니다.

"Gen-Spec 관계형 모델링"에서 Google 검색을 수행하십시오. 일반화 된 엔티티의 속성 (슈퍼 클래스를 호출 할 수있는 OO 프로그래머), 각 특수 엔티티에 대한 별도의 테이블 (하위 클래스) 및 링크를 연결하는 방법에 대한 기사를 찾을 수 있습니다. 모두 함께.

최고의 기사 IMO는 ER 모델링 측면에서 Gen-Spec에 대해 논의합니다. ER 모델을 관계형 모델로 번역 한 다음 SQL 테이블로 변환하는 방법을 알고 있다면 ER에서 Gen-Spec을 모델링하는 방법을 보여 주면 어떻게 해야하는지 알 수 있습니다.

"gen-spec"에서 Google만으로도 볼 수있는 대부분의 사람들은 객체 지향적이지 않고 관계형 지향적입니다. 객체 관계형 임피던스 불일치를 극복하는 방법을 아는 한 그 물건은 유용 할 수 있습니다.

귀하의 디자인은 합리적이며 올바른 정규화 규칙을 따르고 있습니다. 차량 ID와 유형이있는 차량 테이블이 없을 수 있습니다 (예 : 스피드 보트, 자동차 및 Gokarts의 "부모"는 "DistormByUserId"와 같은 물건을 보관할 수 있습니다). 차량 테이블과 스피드 보트 테이블 사이에 하나는 하나의 관계가 있으며, 차량과 스피드 보트/자동차/Gokart 사이에는 1 and-only-1 관계가 있습니다 (예 : 차량에는 스피드 보트에 대해서는 1 개의 레코드 만 가질 수 있습니다. 자동차 또는가 Karts) ... 대부분의 DB는 이에 대한 쉬운 시행 메커니즘을 제공하지는 않습니다.

이러한 종류의 것들을 식별하는 데 도움이되는 정규화 규칙 중 하나는 필드가 테이블의 주요 키에만 의존해야한다는 것입니다. 스피드 보트, 자동차 및 Gokart 테스트 결과가 함께 저장되는 통합 테이블에서 자동차 관련 필드는 테스트 날짜뿐만 아니라 Vechicle ID 및 차량 유형에 따라 다릅니다. 테스트 결과 테이블의 주요 키는 테스트 날짜 + 차량 ID이며, 차량 유형은 테스트 데이터 행을 독특하게 만드는 것이 아닙니다 (예 : 어쨌든 01/01/200912 : 30pm에서 하나의 특정 차량에서 테스트를 수행해야합니다. 그것은 스피드 보트와 자동차입니다 ... 아니요 ... 할 수 없습니다).

나는 정규화 규칙을 특히 잘 설명하지는 않지만 ... 제 3/4 일/5 번째 정상 형태 규칙은 공식적인 설명을 읽을 때 항상 나를 혼란스럽게한다. 그 중 하나 (3/4/5/5)는 기본 키와 기본 키에 따라 필드를 다룹니다. 이 규칙은 기본 키가 올바르게 식별되었다고 가정합니다 (기본 키를 잘못 정의하는 것은 너무 쉽습니다).

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top