0

감사합니다. 학교와 대학에서 정규화를 배웠던 이래로 오랜 시간이 걸렸습니다. 업계에서 일하면서이 이론적 인 일이 종종 당신이해야 할 일을 방해 할 수도 있다는 것을 알게 될 것입니다. 여기 잠시 생각하고있는 것에 대한 예가 있습니다. 나는 당신의 의견을 듣고 싶습니다. 이 방법에 옳고 그름이 있는지 확실하지 않으므로 모든 대답을 환영합니다.n : 1 ~ 2 n : 1,이 표가 제대로 정상화 되었습니까?

시나리오 : 우리는 사람 관리 시스템 (PMS)을 개발하고있다 . 이를 위해 각 개인 (예 : 이름)에 대한 일반 정보, 국가 테이블, 사람의 출신 국가 및 인종 레이스 테이블을 저장하기위한 Person 테이블이 있습니다.

따라서 당신은 바로, 나라와 인종에 연결, 사람에 두 개의 외래 키 열이 있을까?

그러나 내 상사가 나에게 네 번째 테이블을 사용하길 원합니다. PersonType이라고 부를 수 있습니다. PersonType은 국가 및 인종에 대한 외래 키 칼럼과 기본 키로 구성됩니다. 그런 다음 Person 테이블에는 PersonType에 대한 하나의 외부 키 열만 있습니다. 오른쪽 PersonType 및 국가/인종 간의 1 개 관계 : 사람과 PersonType뿐만 아니라 N으로 사이 1 개 관계 :

그러므로 나는 N있을 것입니다? 그냥 사람이 테이블에 직접 외래 키 열을 넣을 수 있기 때문에 제 생각에는

는 PersonType 테이블이 필요하지 않습니다하지만 내 상사는 PersonType이 조합이 유효있는 국가/인종 제한하는 데 사용할 수 있다고 주장한다. 나는 그 논쟁을 이해하지만,이 데이터베이스가 여전히 적절하게 표준화되어 있는지 스스로에게 묻고 있습니다.

는 (물론 우리는 정말 PMS를 개발하는 것이 아니라 나는 상상하기 쉽게하고 나는 우리가 정말 NDA에 의한 개발하는 일에 대해 이야기 할 수 없다 생각했다).

UPDATE 21/10/2016

는 Heres는 테이블 구조는 추상적 인 방법과 같은 방법 :

table person_v1(
    person_id int primarykey, 
    name string, 
    country_id int foreignkey(country), 
    race_id int foreignkey(race) 
) 

table person_v2(
    person_id int primarykey, 
    name string, 
    person_type_id int foreignkey(person_type) 
) 

table person_type(
    person_type_id int primarykey, 
    country_id int foreignkey(country), 
    race_id int foreignkey(race) 
) 

table country(
    country_id int primarykey, 
    name string 
) 

table race(
    race_id int primarykey, 
    name string 
) 

지금까지 귀하의 답변 주셔서 감사합니다

+0

* "Person 테이블에는 PersonType에 대한 하나의 외래 키 열만 있습니다."* person_type_id와 같은 새로운 특성과 몇 가지 새로운 기능 종속성을 도입 할 경우에만. * 그 *는 정규화가 아닙니다. 그것은 대용 키를 사용하고 있습니다. (대리 키는 정규화가 아닌 데이터 압축과 관련이 있습니다.) 정규화는 새로운 특성을 도입하지 않습니다. 나는 하나의 후보 키 (country_code, race_code)를 갖는 person_type {country_code, race_code} 관계가 이미 5NF에 있다고 생각합니다. –

+0

* "내 상사는 PersonType을 사용하여 어떤 국가/민족 조합이 유효한지 제한 할 수 있다고 주장합니다."* 사실입니다. 그리고 그 제약 조건을 강제하는 것이 요구된다면, 네 번째 테이블이 필요합니다. 그러나 실제로는 모국과 인종의 부적합한 조합이 아닙니다. 이것이 실제 상황에 적용되는지는 알 수 없습니다. –

+0

* "네이티브 국가와 인종의 잘못된 조합은 실제로 존재하지 않습니다"* 당신이 옳습니다. 기본적으로 잘못된 조합은 없습니다. 그것은 비즈니스 규칙/논리의 이상이며 내 생각에 그렇지 않으면 구현 될 수 있습니다. Currentyl 우리의 init scrips는 "person_type"에 항목을 만들지 만 가능한 항목 (count (countries) * count (race))의 최대 항목까지 추가 항목을 만들지 않습니다. – xxtesaxx

답변

1

1 : N 또는 M : N 관계의 수는 관계의 정규 형식을 결정하지 않습니다. 문제는 실제로 정규화와는 아무런 관련이 없습니다.

일부 테이블. . .

귀하의 디자인

팔로우 기준을하실 수 있습니다. 국가별로 ISO 3166-1을 따를 것입니다.

create table countries (
    iso_country_code char(3) primary key, 
    country_name varchar(75) not null unique 
); 

insert into countries (iso_country_code, country_name) values 
('USA', 'United States of America'), 
('GBR', 'United Kingdom of Great Britain and Northern Ireland'), 
('MKD', 'Macedonia (the former Yugoslav Republic of)'), 
('ZZZ', 'Unknown country'); -- 'ZZZ' is reserved for a user-assigned value. 

경주는 CDC/HL7 경주 코드를 따를 것입니다. 다른 표준이 있습니다. 그 중 하나가 더 적절할 수 있습니다. http://www.cdc.gov/nchs/data/dvs/race_ethnicity_codeset.pdf

대부분의 응용 프로그램은 각 사람마다 여러 개의 경주 코드를 허용합니다. 에 대한 실제 사실을 무시합니다.이 질문입니다.

create table races (
    cdc_unique_id char(6) primary key, 
    cdc_race_concept varchar(50) not null unique 
); 

insert into races (cdc_unique_id, cdc_race_concept) values 
('2056-0', 'Black'), 
('2106-3', 'White'), 
('2076-8', 'Native Hawaiian or other Pacific islander'), 
('zzzz-z', 'Unknown'); 

create table persons (
    person_id integer primary key, 
    person_full_name varchar(25) not null, 
    iso_country_code char(2) not null 
    default 'ZZZ' 
    references countries (iso_country_code) 
     on update cascade 
     on delete set default, 
    cdc_unique_id char(6) not null 
    default 'zzzz-z' 
    references races (cdc_unique_id) 
     on update cascade 
     on delete set default 
); 

이 세 표는 모두 5NF 이상입니다.

디자인에 잠재적 인 문제가있을 수 있습니다. 은 국가 및 경쟁의 임의 구문 구문 을 허용한다는 점에서 다릅니다. 국가와 인종 대신에 우리는 미국에서 도시와 주에 관해 이야기하고 있다고 상상해보십시오. 도시와 주를 임의로 구분하면 "San Francisco, AL"이 허용됩니다. 그러나 알라바마에는 "샌프란시스코"라는 도시가 없습니다.

그래서 임의의 구문 분석을 허용하면 나쁜 결정이 될 수 있습니다.

상사의 디자인은

-- The same as the table above. 
create table countries (
    iso_country_code char(3) primary key, 
    country_name varchar(75) not null unique 
); 

insert into countries (iso_country_code, country_name) values 
('USA', 'United States of America'), 
('GBR', 'United Kingdom of Great Britain and Northern Ireland'), 
('MKD', 'Macedonia (the former Yugoslav Republic of)'), 
('ZZZ', 'Unknown country'); -- 'ZZZ' is reserved for a user-assigned value. 

-- Also the same as the table above. 
create table races (
    cdc_unique_id char(6) primary key, 
    cdc_race_concept varchar(50) not null unique 
); 

insert into races (cdc_unique_id, cdc_race_concept) values 
('2056-0', 'Black'), 
('2106-3', 'White'), 
('2076-8', 'Native Hawaiian or other Pacific islander'), 
('zzzz-z', 'Unknown'); 

-- This table is new. 
create table person_types (
    iso_country_code char(3) not null 
    default 'ZZZ' 
    references countries (iso_country_code) 
     on update cascade 
     on delete set default, 
    cdc_unique_id char(6) not null 
    default 'zzzz-z' 
    references races (cdc_unique_id) 
     on update cascade 
     on delete set default, 
    primary key (iso_country_code, cdc_unique_id) 
); 

insert into person_types values 
('USA', '2016-3'), 
('USA', '2056-0'), 
('GBR', '2016-3'), 
('GBR', '2056-0'), 

이 "person_types"표는 데이터베이스 설계하지 않는 사실 를 기록합니다. 은 백인과 흑인 인 이 미국과 영국 출신 일 수 있다고 기록합니다. 사실을 기록하는 것이 중요한 경우 에 "person_types"가 포함되어야합니다.

또한이 표는 다른 의견에 언급 된 문제에 영향을받지 않습니다. 당신은 반복적으로 iso_country_code와 cdc_unique_id가 모두 null 인 행을 추가 할 수 없습니다 (not null 제약 조건), iso_country_code 및 cdc_unique_id (primary key 제약 조건) 등을 복제 할 수 없습니다.

개념적으로, 정규화하기 전에 저장할 사실을 결정합니다. 정규화는 스키마에없는 속성을 사용하면 도움이 될 수 없습니다. 그것은 다른 데이터베이스 디자인 작업입니다.

-- Structurally identical to the table above. 
-- Constraints are slightly different. 
-- 
create table persons (
    person_id integer primary key, 
    person_full_name varchar(25) not null, 
    iso_country_code char(2) not null 
    default 'ZZZ', 
    cdc_unique_id char(6) not null 
    default 'zzzz-z', 
    constraint person_types_fk foreign key (iso_country_code, cdc_unique_id) 
    references person_types (iso_country_code, cdc_unique_id) 
     on update cascade 
     on delete set default 
); 

이 네 개의 테이블 모두 적어도 5NF에 있습니다.

차이점은 한 세트의 테이블이 다른 테이블보다 정규화되어 있지 않다는 점입니다.

차이점은 테이블의 한 세트는 다른 하나가이 아니라는 사실을 기록한다는 것입니다.

+0

아주 잘 설명했다. 고맙습니다. – xxtesaxx

0

은의이 테이블을 가정 해 봅시다

CREATE TABLE RaceMeetings 
(country_name VARCHAR(30) NOT NULL, 
    race_name VARCHAR(25) NOT NULL, 
    UNIQUE (country_name, race_name)); 
: 당신과 당신의 상사의 디자인에 공통입니다 내가 무엇을 말할 수에서

, 당신의 디자인이 (하나 개의 테이블)입니다 :

CREATE TABLE People_v1 
(person_name VARCHAR(35) NOT NULL UNIQUE, 
    country_name VARCHAR(30) NOT NULL, 
    race_name VARCHAR(25) NOT NULL, 
    FOREIGN KEY (country_name, race_name) 
    REFERENCES RaceMeetings (country_name, race_name)); 

은 ... 당신은 상사의 디자인이 (두 테이블)입니다 :

CREATE TABLE People_v2 
(person_name VARCHAR(35) NOT NULL UNIQUE); 

CREATE TABLE RaceMeetingAttendance 
(person_name VARCHAR(35) NOT NULL UNIQUE 
    REFERENCES People_v2 (person_name), 
    country_name VARCHAR(30) NOT NULL, 
    race_name VARCHAR(25) NOT NULL, 
    FOREIGN KEY (country_name, race_name) 
    REFERENCES RaceMeetings (country_name, race_name)); 

모두 디자인

  • 이 제한 5NF
  • 에 완전히 정규화 {country_n ame, race_name} 조합을 사용하여 테이블 RaceMeetings에 정의 할 수 있습니다.

귀하의 상사의 디자인은 추가로 6NF이지만 실제적인 이점을 제공하지는 않습니다.

그러나 나는 테이블이 엔티티 또는 엔티티 간의 관계를 모델링해야하지만 둘 다 결코 모델링해서는 안된다는 경험 법칙에 기반한 사장님의 디자인을 선호합니다. 다른 방법으로, "경주 퍼시픽 그랑프리"가 일본에서 개최되는 것과 같은 경주 회의는 사람의 속성으로 나를 공격하지 않습니다. 관계 (사람과 경마 모임의 관계)와 같은 관계에 있으며,이 관계를 모델링하기 위해 별도의 테이블을 사용하는 것이 나를 'RaceMeetingAttendance'라는 이름으로 유용하게 사용할 수 있습니다.

즉, 디자인에는 레이스 모임에 참석하지 않은 사람이 데이터베이스에 존재할 수 없다는 이점이 있습니다.

+0

상세한 답변을 보내 주셔서 감사합니다. 나는 우리의 데이터베이스 구조에 대해 더 잘 이해할 수 있도록 원래의 게시물을 업데이트했다. 나는 너의 의견에 매우 감사한다. 감사합니다, Jan – xxtesaxx