如果我的系统中有两种实体类型:用户和工作(特定工作是该国某处的可用工作职位)。两种实体类型都由Addresses定义。
例如,用户将拥有家庭地址、地点、国家、邮政编码等。工作也将拥有此信息。
我应该使用一个Addresses表还是将其拆分为两个表,例如User_Addresses和Job_Addresses?
单表的想法很简单,但是当涉及到混合两种没有共同点的实体类型的外来Id时,我不知道该怎么想。我将无法添加外键,因为该列可能包含定义User或Job的Id。
另一方面,我不确定是否有两个具有相同列类型的表。
我们通过评论确定——关于你的业务背景和你的问题范围——实际上存在三种不同的相关实体类型,即:
User
Job
Address
我们还定义了涉及所述实体类型的两种不同关系,您通过以下评论提供了有关此类连接的更多详细信息:
- ……[我]n 理论上住在同一个地方的两个人可以使用该系统。
- …[A] 用户绑定到一个地址。
- …[A] 在任何给定时间,作业只能与一个地址相关联。但是两个不同的 Job 可以有相同的地址。
因此,重要的业务规则可以制定如下:
An Address houses zero-one-or-many Users
An Address locates zero-one-or-many Jobs
因此,我推导出了一个简化的 IDEF1X 1 逻辑模型,该模型描述了图 1 中的上述业务规则:
在所述逻辑模型,可以看出,我已分别表示的三种讨论实体类型,并建立(一个)之间的关联Address
和User
和(b)之间的连接如Address
和Job
由所述的装置迁移2所述的Address
PRIMARY KEY(PK)到既User
和Job
,其强制两种不同的一个一对多(1:M)关系,你的方案描述的要求。
因此,我基于上述逻辑模型创建了一个说明性 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.
-- As one would expect, you are free to make use of
-- your preferred (or required) naming conventions.
CREATE TABLE Country
(
CountryCode CHAR(3) NOT NULL,
Name CHAR(30) NOT NULL,
CreatedDateTime DATETIME NOT NULL,
CONSTRAINT PK_Country PRIMARY KEY (CountryCode),
CONSTRAINT AK_Country_Name UNIQUE (Name) -- ALTERNATE KEY.
);
CREATE TABLE Region
(
CountryCode CHAR(3) NOT NULL,
RegionCode CHAR(3) NOT NULL,
Name CHAR(30) NOT NULL,
CreatedDateTime DATETIME NOT NULL,
CONSTRAINT PK_Region PRIMARY KEY (CountryCode, RegionCode),
CONSTRAINT AK_Region_CountryCode_and_Name UNIQUE (CountryCode, Name) -- ALTERNATE KEY.
);
CREATE TABLE Locality
(
CountryCode CHAR(3) NOT NULL,
RegionCode CHAR(3) NOT NULL,
LocalityCode CHAR(3) NOT NULL,
Name CHAR(30) NOT NULL,
CreatedDateTime DATETIME NOT NULL,
CONSTRAINT PK_Locality PRIMARY KEY (CountryCode, RegionCode, LocalityCode),
CONSTRAINT AK_Locality_CountryCode_RegionCode_and_Name UNIQUE (CountryCode, RegionCode, Name) -- ALTERNATE KEY.
);
CREATE TABLE MyAddress
(
AddressId INT NOT NULL,
CountryCode CHAR(3) NOT NULL,
RegionCode CHAR(3) NOT NULL,
LocalityCode CHAR(3) NOT NULL,
Name CHAR(30) NOT NULL,
CreatedDateTime DATETIME NOT NULL,
CONSTRAINT PK_MyAddress PRIMARY KEY (AddressId),
CONSTRAINT FK_from_MyAddress_to_Locality FOREIGN KEY (CountryCode, RegionCode, LocalityCode) -- Composite FOREIGN KEY.
REFERENCES Locality (CountryCode, RegionCode, LocalityCode)
);
CREATE TABLE UserProfile
(
UserId INT NOT NULL,
FirstName CHAR(30) NOT NULL,
LastName CHAR(30) NOT NULL,
BirthDate DATE NOT NULL,
GenderCode CHAR(3) NOT NULL,
Username CHAR(20) NOT NULL,
HouseAddressId INT NOT NULL,
CreatedDateTime DATETIME NOT NULL,
CONSTRAINT PK_UserProfile PRIMARY KEY (UserId),
CONSTRAINT AK_UserProfile_FirstName_LastName_Gender_and_BirthDate UNIQUE -- Composite ALTERNATE KEY.
(
FirstName,
LastName,
GenderCode,
BirthDate
),
CONSTRAINT AK_UserProfile_Username UNIQUE (Username), -- ALTERNATE KEY.
CONSTRAINT FK_from_UserProfile_to_MyAddress FOREIGN KEY (AddressId)
REFERENCES MyAddress (AddressId)
);
CREATE TABLE Job
(
JobNumber INT NOT NULL,
AddressId INT NOT NULL,
Etcetera CHAR(30) NOT NULL,
CreatedDateTime DATETIME NOT NULL,
CONSTRAINT PK_Job PRIMARY KEY (JobNumber),
CONSTRAINT FK_from_Job_to_MyAddress FOREIGN KEY (AddressId)
REFERENCES MyAddress (AddressId)
);
Run Code Online (Sandbox Code Playgroud)
酸交易
与任何关系数据库实现一样,您应该认真考虑使用ACID TRANSACTIONS以保护您正在使用的数据的完整性和一致性。
如果您想直接从单个资源访问用户和地址数据点,创建一个视图(即派生表或虚拟表)会很方便,该视图显示属于名为and的基表的列,例如:UserProfile
MyAddress
CREATE VIEW UserAndAddress AS
SELECT U.UserId,
U.FirstName,
U.LastName,
U.BirthDate,
U.GenderCode,
U.Username,
A.CountryCode,
A.RegionCode,
A.LocalityCode,
A.Postcode,
A.Etcetera
FROM UserProfile U
JOIN MyAddress A
ON U.HouseAddressId = A.AddressId;
Run Code Online (Sandbox Code Playgroud)
这样就可以直接从VIEW中SELECT,而不必每次要检索相关信息时都写JOIN子句和条件。当然,您可以对职位和地址数据采用类似的方法。
如果您需要在实体类型Address
和User
实体类型之间实现多对多 (M:N) 关系(这在其他上下文中并不罕见),则需要对业务规则公式进行一些小的修改,如如下图所示:
A User keeps zero-one-or-many Addresses
An Address is kept by zero-one-or-many Users
因此,我绘制了一个新的逻辑模型来描绘图 2 中的这种情况:
如图所示,包含了一个连接 (a)和 (b)的关联实体,我相应地命名了它;它的 PK 由两个不同的 FOREIGN KEY 组成,每个 FOREIGN KEY 都引用了各自的实体类型。User
Address
UserAddress
我用这种替代安排编码了一个说明性的 DDL 结构:
CREATE TABLE MyAddress
(
AddressId INT NOT NULL,
CountryCode CHAR(2) NOT NULL,
RegionCode CHAR(2) NOT NULL,
LocalityCode CHAR(2) NOT NULL,
Name CHAR(30) NOT NULL,
CreatedDateTime DATETIME NOT NULL,
CONSTRAINT PK_MyAddress PRIMARY KEY (AddressId),
CONSTRAINT FK_from_MyAddress_to_Locality FOREIGN KEY (CountryCode, RegionCode, LocalityCode) -- Composite FOREIGN KEY.
REFERENCES Locality (CountryCode, RegionCode, LocalityCode)
);
CREATE TABLE UserProfile
(
UserId INT NOT NULL,
FirstName CHAR(30) NOT NULL,
LastName CHAR(30) NOT NULL,
BirthDate DATE NOT NULL,
GenderCode CHAR(3) NOT NULL,
Username CHAR(20) NOT NULL,
AddressId INT NOT NULL,
CreatedDateTime DATETIME NOT NULL,
CONSTRAINT PK_UserProfile PRIMARY KEY (UserId),
CONSTRAINT AK_UserProfile_FirstName_LastName_Gender_and_BirthDate UNIQUE -- Composite ALTERNATE KEY.
(
FirstName,
LastName,
GenderCode,
BirthDate
),
CONSTRAINT AK_UserProfile_Username UNIQUE (Username) -- ALTERNATE KEY.
);
CREATE TABLE UserAddress
(
AddressId INT NOT NULL,
UserId INT NOT NULL,
IsPhysical BIT NOT NULL,
IsShipping BIT NOT NULL,
IsBilling BIT NOT NULL,
CreatedDateTime DATETIME NOT NULL,
CONSTRAINT PK_MyAddress PRIMARY KEY (UserId, AddressId), -- Composite PRIMARY KEY.
CONSTRAINT FK_UserAddress_to_User FOREIGN KEY (UserId)
REFERENCES UserProfile (UserId),
CONSTRAINT FK_UserAddress_to_Address FOREIGN KEY (AddressId)
REFERENCES MyAddress (AddressId)
);
Run Code Online (Sandbox Code Playgroud)
如果Job
和之间关系的基数Address
也恰好是(或者,谁知道?在某个时间点变成)M:N 在您的业务领域中,您可以采用与刚才详述的方法相当的方法。
1.对信息建模(综合定义IDEF1X)是被确立为一个非常可取的数据建模技术标准通过标准的美国国家技术研究所(NIST)于1993年12月。它坚实基础的(一)理论著作撰写由始发的的关系模型,即EF科德博士; 关于 (b)实体关系视图,由PP Chen 博士开发;以及 (c) 逻辑数据库设计技术,由 Robert G. Brown 创建。值得注意的是,IDEF1X 是通过一阶逻辑形式化的。
2. IDEF1X 将键迁移定义为“将父实体或通用实体的主键作为外键放置在其子实体或类别实体中的建模过程”。