如何在我的数据库结构中将用户和作业与地址联系起来?

Pat*_*.SE 4 database-design

如果我的系统中有两种实体类型:用户工作(特定工作是该国某处的可用工作职位)。两种实体类型都由Addresses定义。

例如,用户将拥有家庭地址地点国家邮政编码等。工作也将拥有此信息。

实施注意事项

我应该使用一个Addresses表还是将其拆分为两个表,例如User_AddressesJob_Addresses

  • 单表的想法很简单,但是当涉及到混合两种没有共同点的实体类型的外来Id时,我不知道该怎么想。我将无法添加外键,因为该列可能包含定义UserJobId

  • 另一方面,我不确定是否有两个具有相同列类型的表。

MDC*_*CCL 8

商业规则

我们通过评论确定——关于你的业务背景和你的问题范围——实际上存在三种不同的相关实体类型,即:

  • 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 中的上述业务规则:

图 1 - 用户、工作和地址简化的数据模型

在所述逻辑模型,可以看出,我已分别表示的三种讨论实体类型,并建立(一个)之间的关联AddressUser和(b)之间的连接如AddressJob由所述的装置迁移2所述的AddressPRIMARY KEY(PK)到既UserJob,其强制两种不同的一个一对多(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以保护您正在使用的数据的完整性一致性

使用 VIEW 使数据检索更容易

如果您想直接从单个资源访问用户地址数据点,创建一个视图(即派生表或虚拟表)会很方便,该视图显示属于名为and的表的列,例如:UserProfileMyAddress

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子句和条件。当然,您可以对职位地址数据采用类似的方法。

用户和地址之间的多对多关系

如果您需要在实体类型AddressUser实体类型之间实现多对多 (M:N) 关系(这在其他上下文中并不罕见),则需要对业务规则公式进行一些小的修改,如如下图所示:

  • A User keeps zero-one-or-many Addresses
  • An Address is kept by zero-one-or-many Users

因此,我绘制了一个新的逻辑模型来描绘图 2 中的这种情况:

图 2 - 用户和地址简化的替代数据模型

如图所示,包含了一个连接 (a)和 (b)的关联实体,我相应地命名了它;它的 PK 由两个不同的 FOREIGN KEY 组成,每个 FOREIGN KEY 都引用了各自的实体类型。UserAddressUserAddress

我用这种替代安排编码了一个说明性的 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 将键迁移定义为“将父实体或通用实体的主键作为外键放置在其子实体或类别实体中的建模过程”。