조회 테이블의 올바른 사용


25

데이터베이스에서 조회 테이블을 언제 어디서 사용할 지에 대한 경계를 정확하게 설정하는 방법을 정확히 파악하는 데 어려움이 있습니다. 내가 본 대부분의 소스는 내가 너무 많이 가질 수 없다고 말하지만 어떤 시점에서는 데이터베이스가 너무 많은 조각으로 나누어 져 효율적일 수는 있지만 더 이상 관리 할 수없는 것처럼 보입니다. 다음은 내가 작업하고있는 것의 예입니다.

Employees라는 테이블이 있다고 가정 해 보겠습니다.

ID  LName   FName   Gender  Position
1   Doe     John    Male    Manager
2   Doe     Jane    Female  Sales
3   Smith   John    Male    Sales

데이터가 더 복잡하고 수백 개의 행을 포함하는 것으로 가정하십시오. 룩업 테이블로 옮길 수있는 가장 확실한 것은 Position입니다. Positions라는 테이블을 만들고 Positions 테이블의 Foreign 키를 Position 열의 Employees 테이블에 붙일 수 있습니다.

ID  Position
1   Manager
2   Sales

그러나 정보를 관리 할 수 ​​없게되기 전에 정보를 더 작은 조회 테이블로 얼마나 세분화 할 수 있습니까? 성별 테이블을 만들 수 있으며 별도 조회 테이블에서 1은 남성에 해당하고 2는 여성에 해당합니다. LName과 FName을 테이블에 넣을 수도 있습니다. 모든 "John"항목은 ID 1이 John에 해당함을 나타내는 FName 테이블을 가리키는 외래 키 1로 대체됩니다. 그러나이 토끼 구멍을 너무 아래로 내려 가면 직원 테이블이 외래 키의 혼란으로 줄어 듭니다.

ID  LName   FName   Gender  Position
1   1       1       1       1
2   1       2       2       2
3   2       1       1       2

서버가 처리하는 것이 더 효율적일 수도 있고 그렇지 않을 수도 있지만, 서버를 유지하려고하는 응용 프로그램 개발자가 액세스하기가 더 어려워 질 수있는 정상적인 사람에게는 확실히 읽을 수 없습니다. 내 진짜 질문은 얼마나 멀어요? 이런 종류의 일에 대한 "모범 사례"나 적절한 지침이 있습니까? 나는 내가 가지고있는이 특정 문제에 대해 훌륭하고 유용한 지침을 실제로 제시하는 정보를 온라인에서 찾을 수 없습니다. 데이터베이스 디자인은 나에게는 모자이지만 GOOD 데이터베이스 디자인은 매우 새롭기 때문에 지나치게 기술적 인 답변이 내 머리 위에있을 수 있습니다. 도움을 주시면 감사하겠습니다!


5
"조회"테이블을 사용하는 것이 한 가지입니다. 텍스트를 ID 번호로 바꾸는 것은 완전히 다릅니다.
마이크 Sherrill '고양이 리콜'

1
성별이 항상 2 값으로 고정되는 것은 아닙니다! 이제 우리는 성별 전환이 있으므로 응용 프로그램에서 '태어남은 지금 여성'또는 '태어나는 지금은 남성 여성'과 같은 추가 범주가 필요하지 않을 수 있습니다.

@ 마이크, 좋은 의견!
Walter Mitty 2016

내 가게에서 사상가는 남성, 여성, 트랜스 젠더, 네 가지 선택 만 공개하지 않으면 멈출 수있었습니다.
kevinsky 2016

답변:


22

그러나 정보를 관리 할 수 ​​없게되기 전에 정보를 더 작은 조회 테이블로 얼마나 세분화 할 수 있습니까? 성별 테이블을 만들 수 있으며 별도 조회 테이블에서 1은 남성에 해당하고 2는 여성에 해당합니다.

두 가지 다른 문제를 혼합하고 있습니다. 한 가지 문제는 "조회"테이블 사용입니다. 다른 하나는 서로 게이트 키 (ID 번호)를 사용하는 것입니다.

이 테이블부터 시작하십시오.

ID  LName   FName   Gender  Position
1   Doe     John    Male    Manager
2   Doe     Jane    Female  Sales
3   Smith   John    Male    Sales

이와 같은 위치에 대한 "조회"테이블을 작성할 수 있습니다.

create table positions (
  pos_name varchar(10) primary key
);

insert into positions
select distinct position 
from employees;

alter table employees
add constraint emp_fk1
foreign key (position) 
  references positions (pos_name);

원래 테이블은 "조회"테이블을 작성하기 전과 동일하게 보입니다. 또한 직원 테이블은 유용한 사람이 읽을 수있는 데이터를 얻기 위해 추가 조인이 필요 하지 않습니다 .

"조회"테이블을 사용하면 다음과 같이 요약됩니다. 응용 프로그램에 외래 키 참조가 제공하는 입력 값을 제어해야합니까? 그렇다면 항상 "조회"테이블을 사용할 수 있습니다. (대리 키를 사용하는지 여부에 관계없이)

경우에 따라 디자인 타임에 해당 테이블을 완전히 채울 수 있습니다. 다른 경우 사용자는 런타임에 해당 테이블에 행을 추가 할 수 있어야합니다. 또한 새 데이터를 검토하려면 일부 관리 프로세스를 포함해야 할 수도 있습니다. 실제로 ISO 표준 이있는 성별 은 디자인 타임에 완전히 채워질 수 있습니다. 국제 온라인 제품 주문에 대한 거리 이름은 런타임에 추가해야합니다.


2
나는 당신이 그 모든 것을 할 수 있다는 것을 몰랐습니다! 방법이 작동하는 방식은 다소 아름답습니다. 고맙습니다!
Brad Turner

4
이 답변에 투표 할 수 있도록 DBA Stack Exchange에 가입했습니다. 이것은 아름답고 나에게 결코 발생하지 않았습니다. 감사!
CindyH

조회 테이블을 채우는 방법에 감사드립니다. 이 질문을 읽은 이유는 조회 테이블에서 대리 키를 볼 수없는 이점이 있는지 확인하는 것이 었습니다. 당신은 나에게 단일 텍스트 필드가 나타나는 것처럼 좋고 유용하다는 것을 확인했습니다. 고맙습니다.
Sinthia V

8

Employees 테이블에서 "Position"에 대한 조회 만 할 수 있습니다. 확장 가능한 데이터 세트이기 때문입니다.

  • 성별은 자체 설명 (예 : M또는 F)이며 2 개의 값으로 제한되며 CHECK 제약 조건으로 시행 할 수 있습니다. 새로운 성별을 추가하지 않습니다 (정치적 정확성을 무시 함)
  • 이름 "John"은 제한적이고 제한된 데이터 세트의 일부가 아닙니다. 잠재적 인 데이터 세트는 사실상 무한한 지점까지 커서 조회하지 않아야합니다.

새 위치를 추가하려면 조회 테이블에 행을 추가하기 만하면됩니다. 또한 정규화의 한 지점 인 데이터 수정 이상 을 제거합니다.

또한 직원 수가 백만 명이면 varchar보다 tinyint PositionID를 저장하는 것이 더 효율적입니다.

새 열 "봉급 통화"를 추가하겠습니다. CHF, GBP, EUR, USD 등의 키로 조회 테이블을 사용하고 싶습니다. 대리 키를 사용하지 않습니다. 이것은 성별과 같은 CHECK 제약 조건으로 제한 될 수 있지만 위치와 같이 제한적이지만 확장 가능한 데이터 집합입니다. char (3)이 아니라 tinyint 임에도 불구하고 백만 행의 직원 데이터에 나타나는 경우에도 자연 키를 사용하기 때문에이 예제를 제공합니다.

요약하면 조회 테이블을 사용합니다.

  1. 열에 유한하지만 확장 가능한 세트 데이터가있는 경우
  2. 자기 설명이없는 곳
  3. 데이터 수정 이상 을 피하기 위해

1
성별을 찾아보기 테이블에 넣는 한 가지 가능한 이유는 현지화입니다.
a_horse_with_no_name

1
"성별 ... (M 또는 F), 2 값으로 제한 ... 정치적 정확성 볼록 무시"-아이러니하게도, 사람들이 잘못 "성별"하게 만드는 것은 똑같은 정치적 정확성입니다. Masculine ','Feminine ')은'성 '('남성 ','여성 ')을 의미합니다. 문맥이 문법적 성별이면 일반적으로 두 개 이상의 값이 있습니다. 상황이 신생아의 성별을 기록하는 경우, 적어도 4 개의 값이 있습니다 ( '공식적으로 평가되지 않은'및 '공식 평가는 결정적이지 않았습니다'). ps 나는 가혹한 소리를 의미하지 않는다, 나는 아이러니를 즐겼다 :)
어느 날

4
@onedaywhen : "Sex"라는 열의 올바른 값은 "Yes please"입니다. 당신이 아니라면있는 거 영국
GBN

이 용어는 정규화와 관련된 특정 의미가 다르기 때문에 여기에서는 "애 노몰 리즈"라는 용어가 잘못 사용되고 있습니다.
philipxy

5

대답은 "의존"입니다. 만족 스럽지는 않지만 디자인을 밀고 당기는 데 많은 영향이 있습니다. 데이터베이스를 디자인하는 앱 프로그래머가 있다면 ORM이 복잡성을 숨기므로 설명하는 구조가 작동합니다. 보고서를 작성할 때 머리카락을 빼내고 주소를 얻으려면 10 개의 테이블을 조인해야합니다.

사용, 의도 된 사용 및 향후 사용을 위해 설계하십시오. 수의학 비즈니스를위한 데이터베이스를 설계하는 경우 첨단 기술 스타트 업과는 상당히 다른 기능의 크기, 사용법 및 방향에 대한 합리적인 가정이 있습니다.

좋아하는 인용구를 재사용하려면

"현명한 사람은 한 번"내가 아프게 될 때까지 정상화하고 그것이 작동 할 때까지 비정규 화한다 "고 말했다.

어딘가에 달콤한 장소가 있습니다. 내 경험에 따르면 둘 이상의 테이블에 키 ID를 갖는 것이 기본 키를 변경하지 않으면 일부 사람들이 생각하는 것만 큼 심각한 범죄는 아닙니다.

실제 시스템에서 고도로 표준화 된 테이블의이 약식 예제를 가져옵니다.

CREATE TABLE PROPERTY
(ID                          NUMBER(9)           NOT NULL);

CREATE TABLE PROPERTY_TYPE
(ID                          NUMBER(9)           NOT NULL);

CREATE TABLE PROPERTY_LOCALE 
PROPERTY_ID                  NUMBER(9)           NOT NULL,
(LOCALE_ID                   NUMBER(9)           NOT NULL,  --language 
VALUE                        VARCHAR2(200)       NOT NULL);

CREATE TABLE PROPERTY_DEPENDENCY
(PROPERTY_ID                 NUMBER(9)           NOT NULL,
 PARENT_PROPERTY_ID          NUMBER(9)                   ,
 PROPERTY_TYPE_ID            NUMBER(9)           NOT NULL);

이 테이블은 단일 속성 및 부모 자식 속성의 연결된 목록을 설정하며 여기에서 사용됩니다.

  CREATE TABLE CASE_PROPERTY
  (ID                        NUMBER(9)           NOT NULL,
  PARENT_ID                  NUMBER(9),
  CASE_ID                    NUMBER(9)           NOT NULL,
  PROPERTY_ID                NUMBER(9),
  PROPERTY_TYPE_ID           NUMBER(9)           NOT NULL);

한 번의 선택으로 property_id가있는 모든 경우를 가져옵니다.

선택할 목록을 얻자

 Select pl.value, pd.property_id
 from property_locale pl, property_dependency pd
 where pl.property_id = pd.property_id
 and pd.property_type_id = 2;  --example number

이제 property_types가 3과 4와 5인지 여부에 관계없이 사례의 모든 속성을 선택하십시오.

SELECT   cp2.case_id,
         (SELECT   pl.VALUE
            FROM   case_property cp, property_locale pl
           WHERE       cp.property_id = pl.property_id
                   AND CP.PROPERTY_TYPE_ID = 2
                   AND pl.locale_id = 2
                   AND cp.case_id = cp2.case_id)
            AS VALUE1,
         (SELECT   pl.VALUE
            FROM   case_property cp, property_locale pl
           WHERE       cp.property_id = pl.property_id
                   AND CP.PROPERTY_TYPE_ID = 34
                   AND pl.locale_id = 2
                   AND cp.case_id = cp2.case_id)
            AS VALUE2,
         (SELECT   pl.VALUE
            FROM   case_property cp, property_locale pl
           WHERE       cp.property_id = pl.property_id
                   AND CP.PROPERTY_TYPE_ID = 4
                   AND pl.locale_id = 2
                   AND cp.case_id = cp2.case_id)
            AS VALUE3
  FROM   case_property cp2
 WHERE   cp2.case_id = 10293  

이것은 당신이 이것을 다루는보다 우아한 방법을 사용할 때조차도 아파요. 그러나 사례에 하나의 property_id 만있는 속성을 분류하여 약간의 비정규 화를 추가하면 훨씬 좋습니다.

테이블이 너무 많거나 부족한 경우를 확인하려면 응용 프로그램, 보고서 및 연간 분석에 사용할 질문으로 데이터베이스를 쿼리하십시오.


5
ID 번호는 정규화와 관련이 없습니다. 모든 테이블에 ID 번호가 있다고해서 5NF 또는 3NF라는 의미는 아닙니다. 해당 테이블에서 사용 가능한 데이터를 얻으려면 많은 조인을 수행해야 함을 의미 합니다.
Mike Sherrill 'Cat Recall'11
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.