概念的に言えば、ビジネス環境ではOrderとAddressは密接に関連しているアイデアですが、実際には2つの個別のエンティティタイプであり、それぞれに独自の適用可能なプロパティ(または属性)と制約があります。
したがって、前述のコメントで述べたように、@ Erikに同意します。データベースの論理レイアウトを編成して、他の要素を宣言する必要があります。
- アドレス情報を保持する1つの個別のテーブル。
- お客様固有の詳細を保持する1つのテーブル。
- Orderデータポイントを囲む1つのテーブル。そして
- Customer(s)とAddress(es)の間の関連付けに関するファクトを含む1つのテーブル。
以下で例を示します。
解説IDEF1X図
写真は千の言葉に値するので、図1に示すIDEF1Xダイアグラムを作成して、私の提案によって開かれた可能性のいくつかを示します。
顧客、住所、およびそれらの関連付け
実例で示したように、エンティティタイプCustomer aとAddressの間の多対多(M:N)カーディナリティ比との関連付けを描きました。ご存知のように、お客様は複数のアドレスを長期間または同時に保持でき、同じアドレスを複数のお客様が共有できるため、このアプローチは将来の柔軟性を提供します。
特定のアドレスは、1対多(1:M)のお客様がいくつかの方法で使用できます。たとえば、「物理」と定義したり、「配送」や「請求」に設定したりできます。おそらく、同じAddressインスタンスが前述の目的のそれぞれを同時に果たすことができます。または、異なるAddressオカレンスが残りの1つをカバーする一方で、2つの用途をカバーすることもできます。
a一部のビジネス環境では、お客様は個人または組織(スーパータイプとサブタイプの構造に関するこの回答で詳細に示されているように、わずかに異なる配置を意味する状況)のいずれかになりますが、簡単な例を提供することを目的として、ここにはその可能性を含めないでください。データベースでその状況をカバーする必要がある場合は、前のリンクの投稿に、上記の要件を解決する方法が示されています。
Order、Address、CustomerAddress、Address Roles
通常、注文に必要な住所は、発送用と請求用の2種類のみです。このようにして、同じAddressインスタンスが個々のOrderの両方のロールを満たすことができますが、各ロールはそれぞれのプロパティ、つまりShippingAddressIdまたはBillingAddressIdによって示されます。
Orderは、2つのマルチプロパティFOREIGN KEY を使用して、CustomerAddress連想エンティティタイプを介してAddressに関連付けられます。
- (CustomerNumber、ShippingAddressId)、および(CustomerNumber、BillingAddressId)、
どちらもCustomerAddressマルチプロパティPRIMARY KEYをポイントしています。
- (CustomerNumber、AddressId)
...規定ということは()というビジネスルールを表すのに役立ちます注文インスタンスが(B)で独占的にリンクしなければならないアドレスの発生は、以前に特定の関連付けられたカスタマー作られたその秩序、そして決してランダム非(C)との顧客 -関連住所。
(1)住所および(2)CustomerAddress関連付けの履歴
アドレス情報を変更する可能性を提供する場合は、すべてのデータ変更を追跡する必要があります。このようにして、Addressを、独自のAddressHistoryを維持する「監査可能な」エンティティタイプとして表現しました。
CustomerとAddressの間の接続の性質も1つ以上の変更の影響を受ける可能性があるため、CustomerAddressHistoryエンティティタイプを使用して、このような関連付けを「監査可能な」関連付けとして扱う可能性も示しました。
この点で、Q&Aで扱われたさまざまな要因はありません。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 <> fiddleでテストしました。
History
テーブル
次の質問からの抜粋は非常に重要です。
私が探しているのは、住所を設定する方法です。そのため、住所を編集しても、顧客が住所を更新したり移転したりしても、注文は影響を受けません。
することを確保する上でのテーブル援助注文は、に影響されないアドレスのすべての「前」行はそれぞれに保持する必要があるとして、変更テーブルと、必要なときに照会することができます。これらの2つのテーブルに対するUPDATEおよびDELETE操作は禁止する必要があります(履歴を変更しようとすると、法的にマイナスの影響が及ぶこともあります)。AddressHistory
CustomerAddressHistory
History
で囲まれた値の間に含まれる間隔は、特定の「過去」の行が「存在」、「現在」、または「有効」と見なされた期間全体AddressHistory.CreatedDateTime
をAddressHistory.AuditedDateTime
表します。同様の考慮事項が行に適用されます。Address
CustomerAddressHistory
CustomerAddress.IsActive
BIT(ブーリアン)カラムを特定するかどうかを指摘することを意図されているAddress
行はによって「使用可能」であるCustomer
行またはありません。たとえば、「false」に設定されている場合、顧客がそのアドレスを使用していないため、新しい注文に使用できないという事実を伝えます。
注:一方、新しい注文が有効になるたびに住所情報を入力する必要があるシステムがいくつかあります(何度も繰り返して)、過去の注文に使用された住所は決して消去されません(したがって)注文はによって影響されないアドレス)の変更。
この一連の行動には、かなりの量の冗長性が明らかに伴う可能性がありますが、ビジネスドメインの正確な情報要件によっては機能する可能性があるため、その長所と短所も評価することをお勧めします。
データ検索
「現在」、「現在」または「有効な」バージョンアドレス発生の行として含まれなければならないAddress
テーブルが、以前の「状態」を選択するアドレスを FROM AddressHistory
(又はからCustomerAddressHistory
)テーブルは簡単であり、それはよいですあなたのSQLコーディングスキルを強化するための興味深い演習になります。
コメントで言及した状況の1つに関して、個々のAddress
行の「最後から2番目のバージョン」をそのAddressHistory
から取得する場合は、手元の特定の値と一致するMAX(AddressHistory.AuditedDateTime)
とを考慮する必要があります。AddressHistory.AddressId
Address.AddressId
この点で、少なくともリレーショナルデータベースを構築する場合は、最初に(該当するビジネスルールに基づいて)対応する概念スキーマを定義し、その後で後続の論理 DDL配置を宣言すると非常に便利です。これらの基本的な要素の安定した信頼できるバージョン(もちろん、時間とともに進化する可能性があります)を入手したら、操作(INSERT、UPDATE、DELETE、およびSELECT操作またはそれらの組み合わせを介して)を行うための最良の方法を分析および決定するときが来ました。データについて。
エンドユーザーの認識、見解、アプリケーションプログラムの支援
明らかに、抽象化の外部レベルでは、住所情報は(エンドユーザーによって)Orderの一部として認識されますが、これには何の問題もありませんが、モデル作成者がそのような問題のデータベース。この点で、たとえば「完全な」注文を印刷する(非常に実現可能)必要がある場合は、いくつかのJOIN演算子とWHERE句(有効期間を考慮して)を使用してオンデマンドで「再現」できます。など)将来の消費のためにビューで修正され、関連する結果セットが関連するアプリケーションプログラムに送信され、必要に応じてフォーマットが拡張されます。
もちろん、注文が発効しているときは、アプリケーションプログラムも非常に役立ちます。たとえば、デスクトップ/モバイルアプリウィンドウまたはウェブページでは次のことができます。
- 関連するお客様が「使用可能」として(を介して)確立したアドレスのみを表示します。
CustomerAddress.IsActive
- お客様が(を介して)課金サービスを有効にしたすべてのアドレスを一緒にリストします。そして
CustomerAddress.IsBilling
- お客様が配送サービス用に(を介して)定義したすべての住所をグループ化します。
CustomerAddress.IsShipping
このようにして、GUIで関連するすべてのプロセス(つまり、コンピュータ化されたシステムの外部レベルの抽象化)を容易にします。
推奨読書
あなたは(今は削除されたコメントで)健全なデータベース文献についてのいくつかのポインタを要求しました。したがって、理論的な資料については、チューリング賞の受賞者であり、もちろん、データのリレーショナルモデルの唯一の創始者であるEF Codd博士が執筆したすべての研究を読むことを強くお勧めします(おそらく、これまで以上に関連性が高まっています)。このリストには、彼の途方もなく影響力のある記事や論文のいくつかが含まれています。
前述のリストに含まれていない2つの重要な作品は、正確には、彼のACM Turing Award Lectureと題するRelational Database:A Practical Foundation for Productivity、1981年から出版されたThe Relational Model for Database Management:Version 2です。 1990年に。
上の概念設計のフロント、インフォメーションモデリングのための統合された定義(IDEF1X)は、米国の1993年12月における標準として定義された真剣に推奨技術である米国国立標準技術研究所(NIST)。