mysql – 如何建模属性和所有者之间的关系(a)以及(b)属性和租户之间的关系?

我有一个数据库设计,我遇到两个表的问题.我有一个Users表和一个Properties表.属性表可能只有0,1或2个用户,我们称之为所有者和租户,每个用户(每个属性)只有一个用户,而用户可能是许多属性中的所有者或租户.

所以,根据案例,这是我的两个选择:

>在属性表中有两个外键(因为属性引用的最大用户数为2而不是N),称为owner_id和ten​​ant_id,它们引用Users表.
>有一个N:M中间表,其中包含user_id和property_id,以及另一列,用于指示该属性中的用户类型(例如boolean 1 = owner,0 = tenant).

哪个是最好的设计选择?

澄清:

>用户具有名称和电子邮件,属性为街道及其编号作为属性.
>用户可能只是财产中的所有者或租户,而不是两者,因为所有者暗示他拥有该财产(他是否居住在那里),而租户是实际居住在那里的另一个用户,因此需要存在添加租户之前的所有者.
>属性可能没有分配用户.

最佳答案
商业规则

所以,(1)在我们进行了一些审议via comments and chat之后,(2)一旦你与客户和同事讨论了这些可能性,事实上已经确定:

>属性具有零个或多个所有者,每个所有者必须是用户
>用户是零个或多个属性的所有者
>属性具有零个一个或多个租户,每个租户必须是用户
>用户是零一个或多个属性的承租人
>物业由其街道及其编号的组合唯一标识
>用户由其EmailAddress唯一标识

因此,在您的业务环境中 – 在其他方面,在实体类型Property和User之间存在基数多对多(M:N)的两个不同的概念级关联(或关系).

说明IDEF1X图

因此,我创建了一个IDEF1X1图表,该图表整合了上面制定的业务规则,如图1所示:

如图所示,每个实体类型 – 它是关联的还是独立的 – 都是通过其独立的框来描绘的.

我将(a)所有权和(b)租赁描述为两种不同的关联实体类型,因为它们虽然非常相似,但它们代表了您业务领域中两种不同的感兴趣事物的原型,因此单独管理它们非常方便,例如, :

>除了

>仅通过真或假的属性保留给定用户是房产的承租人或所有者的事实 – 例如,is_owner和is_tenant-,

>你可能也有兴趣

>保持在系统中注册的所有所有权和租赁实例的确切时间点,从而为所述实体类型建立与时间相关的属性 – 例如,created_datetime-将是非常有利的.

>将来,这些实体类型中的一个可能需要跟踪不适用于另一个的某些属性,因此从一开始就离散地管理它们,从而构成一个更可扩展和多功能的概念架构.

值得一提的是,在图中,user_id属性从(i)用户实体类型迁移到(ii)所有权和(ii)租赁分别作为owner_id和ten​​ant_id迁移 – 您在问题中提供的完全描述性的角色名称 – .

说明性逻辑SQL-DDL设计

然后,根据上面详细介绍的IDEF1X图,我编写了如下声明的说明性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 user_profile (
    user_id          INT      NOT NULL,
    first_name       CHAR(30) NOT NULL,
    last_name        CHAR(30) NOT NULL,
    gender_code      CHAR(3)  NOT NULL,
    birth_date       DATE     NOT NULL,
    email_address    CHAR(30) NOT NULL,
    created_datetime DATETIME NOT NULL,
    --
    CONSTRAINT user_profile_PK  PRIMARY KEY (user_id),
    CONSTRAINT user_profile_AK1 UNIQUE ( -- Multi-column ALTERNATE KEY.
        first_name,
        last_name,
        gender_code,
        birth_date
    ),
    CONSTRAINT user_profile_AK2 UNIQUE (email_address) -- Single-column ALTERNATE KEY.
);

CREATE TABLE property (
    property_id      INT      NOT NULL, 
    street           CHAR(30) NOT NULL,
    number           CHAR(30) NOT NULL,
    created_datetime DATETIME NOT NULL,
    -- 
    CONSTRAINT property_PK PRIMARY KEY (property_id),
    CONSTRAINT property_AK UNIQUE      (street, number) 
);

CREATE TABLE ownership (
    property_id      INT      NOT NULL, 
    owner_id         INT      NOT NULL,   
    created_datetime DATETIME NOT NULL,
    --
    CONSTRAINT property_PK              PRIMARY KEY (property_id, owner_id),
    CONSTRAINT ownership_to_property_FK FOREIGN KEY (property_id)
        REFERENCES property (property_id),
    CONSTRAINT ownership_to_owner_FK    FOREIGN KEY (owner_id)
        REFERENCES user_profile (user_id)
);

CREATE TABLE tenancy (
    property_id      INT      NOT NULL, 
    tenant_id        INT      NOT NULL,   
    created_datetime DATETIME NOT NULL,
    --
    CONSTRAINT tenancy_PK             PRIMARY KEY (property_id, tenant_id),
    CONSTRAINT tenancy_to_property_FK FOREIGN KEY (property_id)
        REFERENCES property (property_id),
    CONSTRAINT tenancy_to_tenant_FK   FOREIGN KEY (tenant_id)
        REFERENCES user_profile (user_id)
);

因此,在这种逻辑层次的设计中:

>每个基表代表一个单独的实体类型(通过相同的基表来防止通过表示不同的含义和意图而引入的歧义);
>每列代表相应实体类型的特定属性;
>为每个列固定一个特定的数据类型,以确保它包含的所有值都属于一个定义良好的集合,无论是INT,DATETIME,CHAR等;和
>以声明方式配置多个约束,以保证所有表中保留的行形式的断言符合概念架构中确定的业务规则.

所有这些都与Dr. Edgar Frank Codd在其relational model中的规定一致(就编写本文时结构化查询语言许可的能力而言).

当然,使用这种逻辑布局,您仍然可以,例如,以BOOLEAN形式派生给定用户是否是特定属性的所有者,借助于产生标量值的SELECT操作,该标量值计算为“True”或’False’,可以从共享该数据库的一个或多个(现在或将来)应用程序访问.

使用相同的逻辑级安排覆盖初始业务规则

这些方面现在大多是轶事,但一些最初的业务规则是:

>属性具有零或一个所有者,必须是用户
>用户是零个或多个属性的所有者
>属性具有零或一个租户,必须是用户
>用户是零个或多个属性的承租人

并且可以使用先前讨论的相同逻辑设计来处理它们,通过另外两个约束,将所有权和租赁表中的property_id列声明为ALTERNATE KEY,即:

ALTER TABLE ownership
    ADD CONSTRAINT UNIQUE ownership_AK (property_id);

ALTER TABLE tenancy
    ADD CONSTRAINT UNIQUE tenancy_AK (property_id);

这显示了本答案中提出的安排所提供的多功能性的其他方面(对未来的访客有帮助).

尾注

1信息建模的集成定义(IDEF1X)是一种非常值得推荐的数据建模技术,由美国国家标准与技术研究院(NIST)于1993年12月作为标准建立.它完全基于(a)关系模型的创始人,即E. F. Codd博士撰写的一些理论着作; (b)entity-relationship view,由Dr. P. P. Chen开发;以及(c)由Robert G. Brown创建的逻辑数据库设计技术.

转载注明原文:mysql – 如何建模属性和所有者之间的关系(a)以及(b)属性和租户之间的关系? - 代码日志