개념적으로 말하자면 비즈니스 환경에서 주문 과 주소 는 밀접하게 관련되어있는 아이디어 이지만 사실상 각각 고유 한 적용 가능한 속성 (또는 속성)과 제약 조건이있는 두 개의 개별 엔티티 유형입니다.
따라서 이전에 의견에서 언급했듯이 @Erik에 동의하며 다른 요소 중에서 선언하는 데이터베이스의 논리적 레이아웃을 구성해야합니다.
- 주소 정보 를 유지하기위한 하나의 개별 테이블 ;
- 고객 별 세부 정보 를 유지하는 하나의 테이블 ;
- 주문 데이터 포인트 를 묶는 하나의 테이블 ; 과
- 고객 과 주소 간의 연관에 관한 사실을 포함하는 하나의 테이블 ;
아래 예를 들어 보겠습니다.
설명 IDEF1X 다이어그램
그림은 천 단어의 가치가 있으므로 그림 1 에 표시된 IDEF1X 다이어그램을 만들어 내 제안에 의해 열린 가능성을 보여줍니다.
고객 , 주소 및 관련 협회
입증 된 바와 같이, 엔티티 유형 고객 a 와 주소 사이의 다 대다 (M : N) 카디널리티 비율과의 연관성을 묘사했습니다 . 아시다시피 고객 은 시간이 지남에 따라 또는 여러 개의 주소 를 동시에 유지할 수 있고 여러 고객 이 동일한 주소 를 공유 할 수 있기 때문에이 접근 방식은 미래의 유연성을 제공합니다 .
특정 주소 는 일대 다 (1 : M) 고객이 여러 가지 방법으로 사용할 수 있습니다 . 예를 들어, 그것은으로 정의 할 수 있습니다 물리적 및 / 또는이를 설정할 수 있습니다 배송 및 / 또는에 대한 청구 . 아마도 동일한 Address 인스턴스가 앞에서 언급 한 각 목적을 동시에 수행 할 수 있거나 다른 Address 발생이 나머지 용도를 커버하는 동안 두 가지 용도를 처리 할 수 있습니다 .
a 일부 비즈니스 환경에서 고객 은 개인 또는 조직 (수퍼 타입 하위 유형 구조에 대한 이 답변에서 자세히 설명한대로 약간 다른 배치를 암시하는 상황) 일 수 있지만 간단한 예를 제공하려는 목적으로 결정했습니다. 그 가능성을 여기에 포함시키지 마십시오. 데이터베이스에서 해당 상황을 처리해야하는 경우 이전 링크의 게시물에 해당 요구 사항을 해결하는 방법이 표시됩니다.
주문 , 주소 , 고객 주소 및 주소 역할
일반적으로 주문 에는 두 가지 종류의 주소 만 필요합니다 . 하나는 배송 용 이고 다른 하나는 청구 용 입니다. 이러한 방식으로, 동일한 Address 인스턴스 는 개별 Order에 대한 두 역할 을 모두 채울 수 있지만 각 역할 은 각각의 특성 (예 : ShippingAddressId 또는 BillingAddressId)으로 표시 됩니다.
주문 은 두 개의 다중 속성 FOREIGN KEY 를 통해 CustomerAddress 연관 엔티티 유형을 통해 Address 와 연결됩니다 .
- ( CustomerNumber , ShippingAddressId ) 및 ( CustomerNumber , BillingAddressId ),
둘 다 CustomerAddress 다중 속성 PRIMARY KEY를 가리키는
- ( CustomerNumber , AddressId )
… (a) 주문 인스턴스는 (b) 해당 주문을 한 특정 고객 과 이전에 연결된 주소 발생 과 (c) 무작위로 고객이 아닌 - 관련 주소 .
(1) 주소 및 (2) CustomerAddress 연관에 대한 히스토리
주소 정보 를 수정할 수있는 가능성을 제공하려면 모든 데이터 변경 사항을 추적해야합니다. 이런 방식으로 Address 는 자신의 AddressHistory 를 유지하는“감사 가능한”엔티티 유형 으로 묘사 했습니다 .
고객 과 주소 간의 연결 특성 도 하나 이상의 수정을 겪을 수 있기 때문에 CustomerAddressHistory 엔티티 유형 으로 인해 이러한 연결을 "감사 가능한"것으로 취급 할 수있는 가능성도 설명했습니다 .
이와 관련하여 Q & A No. 1 과 Q & A 번호 데이터베이스에서 시간적 기능을 활성화 하는 것과 관련 하여 2 는 실제로 관련이 있습니다.
예시적인 SQL-DDL 논리 레이아웃
결과적으로 위에서 표시하고 설명한 다이어그램의 관점에서, 나는 다음과 같은 논리 수준 배열을 선언했습니다 (정확도로 요구 사항을 충족하도록 조정할 수 있음).
-- You should determine which are the most fitting
-- data types and sizes for all your table columns
-- depending on your business context characteristics.
-- Also, you should make accurate tests to define the
-- most convenient INDEX strategies based on the exact
-- data manipulation tendencies of your business domain.
-- As one would expect, you are free to utilize
-- your preferred (or required) naming conventions.
CREATE TABLE Customer (
CustomerNumber INT NOT NULL,
SpecificAttribute CHAR(30) NOT NULL,
ParticularAttribute CHAR(30) NOT NULL,
CreatedDateTime DATETIME NOT NULL,
--
CONSTRAINT Customer_PK PRIMARY KEY (CustomerNumber)
);
CREATE TABLE Address (
AddressId INT NOT NULL,
SpecificAttribute CHAR(30) NOT NULL,
ParticularAttribute CHAR(30) NOT NULL,
CreatedDateTime DATETIME NOT NULL,
--
CONSTRAINT Address_PK PRIMARY KEY (AddressId)
);
CREATE TABLE CustomerAddress (
CustomerNumber INT NOT NULL,
AddressId INT NOT NULL,
IsPhysical BIT NOT NULL,
IsShipping BIT NOT NULL,
IsBilling BIT NOT NULL,
IsActive BIT NOT NULL,
CreatedDateTime DATETIME NOT NULL,
--
CONSTRAINT CustomerAddress_PK PRIMARY KEY (CustomerNumber, AddressId),
CONSTRAINT CustomerAddressToCustomer_FK FOREIGN KEY (CustomerNumber)
REFERENCES Customer (CustomerNumber),
CONSTRAINT CustomerAddressToAddress_FK FOREIGN KEY (AddressId)
REFERENCES Address (AddressId)
);
CREATE TABLE MyOrder (
CustomerNumber INT NOT NULL,
OrderNumber INT NOT NULL,
ShippingAddressId INT NOT NULL,
BillingAddressId INT NOT NULL,
SpecificAttribute CHAR(30) NOT NULL,
ParticularAttribute CHAR(30) NOT NULL,
OrderDate DATE NOT NULL,
CreatedDateTime DATETIME NOT NULL,
--
CONSTRAINT Order_PK PRIMARY KEY (CustomerNumber, OrderNumber),
CONSTRAINT OrderToCustomer_FK FOREIGN KEY (CustomerNumber)
REFERENCES Customer (CustomerNumber),
CONSTRAINT OrderToShippingAddress_FK FOREIGN KEY (CustomerNumber, ShippingAddressId)
REFERENCES CustomerAddress (CustomerNumber, AddressId),
CONSTRAINT OrderToBillingAddress_FK FOREIGN KEY (CustomerNumber, BillingAddressId)
REFERENCES CustomerAddress (CustomerNumber, AddressId)
);
CREATE TABLE AddressHistory (
AddressId INT NOT NULL,
AuditedDateTime DATETIME NOT NULL,
SpecificAttribute CHAR(30) NOT NULL,
ParticularAttribute CHAR(30) NOT NULL,
CreatedDateTime DATETIME NOT NULL,
--
CONSTRAINT AddressHistory_PK PRIMARY KEY (AddressId, AuditedDateTime),
CONSTRAINT AddressHistoryToAddress_FK FOREIGN KEY (AddressId)
REFERENCES Address (AddressId)
);
CREATE TABLE CustomerAddressHistory (
CustomerNumber INT NOT NULL,
AddressId INT NOT NULL,
AuditedDateTime DATETIME NOT NULL,
IsPhysical BIT NOT NULL,
IsShipping BIT NOT NULL,
IsBilling BIT NOT NULL,
IsActive BIT NOT NULL,
CreatedDateTime DATETIME NOT NULL,
--
CONSTRAINT CustomerAddressHistory_PK PRIMARY KEY (CustomerNumber, AddressId, AuditedDateTime),
CONSTRAINT CustomerAddressHistoryToCustomerAddress_FK FOREIGN KEY (CustomerNumber, AddressId)
REFERENCES CustomerAddress (CustomerNumber, AddressId)
);
살펴 보려면 SQL Server 2017에서 실행 되는이 db <> 바이올린에서 테스트했습니다 .
History
테이블
귀하의 질문에서 다음과 같은 발췌 내용이 매우 중요합니다.
내가 찾고있는 것은 주소를 설정하여 편집 할 때 고객이 주소를 업데이트하거나 이전한다는 사실에 영향을받지 않습니다.
AddressHistory
및 CustomerAddressHistory
보장의 테이블 원조 주문 에 의해 영향을받지 않습니다 주소 모든 "이전"행이 각각 유지해야한다로 변경 History
테이블과 필요에 조회 할 수 있습니다. 이 두 테이블에 대한 UPDATE 및 DELETE 조작은 금지되어야합니다 (히스토리 변경을 시도하면 법적으로 부정적인 영향을 줄 수 있음).
간격 에 둘러싸인 값 사이에 포함 AddressHistory.CreatedDateTime
하고 AddressHistory.AuditedDateTime
전체의 약자 기간 특정 "과거"그 동안 Address
행, "현재"또는 "효과" "현재"간주되었다. CustomerAddressHistory
행 에도 비슷한 고려 사항이 적용됩니다 .
CustomerAddress.IsActive
BIT (boolean)에 열이 어떤 것인지 지적 의미 Address
행에 의해 "가능"인 Customer
행의 여부; 예를 들어, '거짓'으로 설정된 경우 고객 이 더 이상 해당 주소를 사용하지 않으므로 새 주문에 사용할 수 없다는 사실을 전달합니다 .
참고 : 반면에, 나는 새로운 주문 이 발효 될 때마다 주소 정보가 (때로는 반복적으로) 입력되어야 하며 과거 주문에 사용 된 주소 가 지워지지 않는 시스템을 보았습니다 (따라서) 주문은 영향을받지 않는 주소 )로 변경됩니다.
이 작업 과정에는 많은 양의 중복성이 결정적으로 포함될 수 있지만 비즈니스 도메인의 정확한 정보 요구 사항에 따라 작동 할 수 있으므로 장단점도 평가할 수 있습니다.
데이터 검색
의 "현재", "현재"또는 "유효"버전 주소 발생이있는 행으로 포함되어야 Address
테이블하지만 이전의 "상태"를 선택한 주소 로부터 AddressHistory
(또는 행 CustomerAddressHistory
) 테이블은 간단하고, 월 SQL 코딩 기술을 향상시키는 흥미로운 연습이 되십시오.
개별의 "마지막 버전으로 두 번째"검색 할 경우, 주석에서 언급 한 상황 중 하나에 대하여 Address
그 FROM 행을 AddressHistory
, 당신은 계정에 걸릴해야 MAX(AddressHistory.AuditedDateTime)
하고, AddressHistory.AddressId
특정 일치 Address.AddressId
손에서 값입니다.
이와 관련하여 (적어도 관계형 데이터베이스를 구축 할 때는) 먼저 해당하는 개념 스키마 (해당 비즈니스 규칙에 따라 )를 정의한 후 후속 논리 DDL 배열 을 선언 하는 것이 매우 편리합니다 . 시간이 지남에 따라 진화 할 수있는 이러한 기본 요소의 안정적이고 안정적인 버전을 확보 한 후에는 (INSERT, UPDATE, DELETE 및 SELECT 작업 또는 이들의 조합을 통해) 조작하는 가장 좋은 방법을 분석하고 결정해야합니다. 데이터 관련.
최종 사용자의 인식, 견해 및 응용 프로그램 지원
분명히, 외부 추상화 레벨에서, 주소 정보는 (최종 사용자에 의해) Order의 일부로 인식되며 , 그에 아무런 문제가 없지만, 모델러가 중요한 부분을 설계해야한다는 의미는 아닙니다. 그런 문제의 데이터베이스. 이 시점에서, 예를 들어, "전체" 주문을 인쇄해야하는 경우 (매우 타당 함) 몇몇 JOIN 연산자와 WHERE 절의 도움을 받아 주문형 주문을 "재생산"할 수 있습니다 (유효 기간 관련 고려 사항 포함) 등) 은 향후 소비에 대한 관점 에서 고정되어 관련 결과 프로그램을 관련 응용 프로그램에 전송하여 필요에 따라 형식을 향상시킬 수 있습니다.
물론, 주문 이 시행 될 때 응용 프로그램도 매우 도움이 될 것입니다 . 예를 들어 데스크톱 / 모바일 앱 창 또는 웹 페이지는 다음을 수행 할 수 있습니다.
- 관련 고객 이 "사용 가능"으로 설정 한 주소 만 표시합니다 (를 통해 ).
CustomerAddress.IsActive
- 고객 이 청구 서비스에 사용하도록 설정 한 모든 주소 를 함께 나열합니다 (를 통해 ). 과
CustomerAddress.IsBilling
- 고객 이 운송 서비스를 위해 정의한 모든 주소 를 그룹화합니다 (를 통해 ).
CustomerAddress.IsShipping
이러한 방식으로 GUI에서의 모든 관련된 프로세스 (즉, 컴퓨터 시스템의 외부 추상화 레벨)를 용이하게한다.
추천 독서
사운드 데이터베이스 문헌에 대한 몇 가지 포인터를 요청했습니다 (이제 주석에서 삭제). 따라서에 관해서는 이론적 소재, 내가보기 엔 당신이 쓴 모든 일을 읽을 것을 조언 박사 EF 커드 하는 튜링 상 , 물론,받는 사람 및 단독 발신자 의 관계형 데이터 모델 (어쩌면 지금보다 관련성이 어느 때보를). 이 목록 에는 그의 영향력있는 기사와 논문 이 포함되어 있습니다.
상기 목록에 포함되지 않은 두 가지 중요한 작품은, 정확하게, 자신의 ACM 튜링 상 강의는받을 수 있습니다 생산성을위한 실용 재단 : 관계형 데이터베이스를 1981 년, 그의 책은 원화 데이터베이스 관리를위한 관계형 모델 : 버전 2 , 출판 되었음 1990 년.
온 개념 설계 앞, 정보 모델링을위한 통합 정의 (IDEF1X는) 미국이 1993 년 12 월 표준으로 정의 된 심각 추천 기술입니다 국립 표준 기술 연구소 (NIST).