3

我在为基于 java 的 Web 应用程序定义适当的数据库设计时遇到了一些麻烦。我有 3 个表(标签、DT 和属性),我的场景如下。每个 Tag 可以包含多个 Dts,每个 DT 可以分配给不同的 Tag,每个 DT 有多个 Properties,每个 Property 可以在多个 DT 中使用。将 DT 分配给 Tag 时,用户可以为其所有属性设置值。

我的问题是,我如何定义一个关系,以便每个标签都可以根据分配给它的 DT 具有其属性值。我的设计中缺少什么表格和关系。然后我必须基于这个数据库创建相对实体。

Tag1==> DT1 ==> Initial values1, property values set 1 ; 
Tag2==> DT1 ==> Initial values1, property values set 2 ;

这是db图。并提前感谢您的帮助。

在此处输入图像描述

这是一些示例数据

在此处输入图像描述

4

2 回答 2

2

在我看来,您设计的核心问题是代理键的使用。不必总是为表创建数字单列键。即使你这样做了,这也不能保证你不会有重复。事实上,这迫使系统在您的表上保留更多索引,这是一项额外的工作。

  1. 一些概念:

    • 我对表名使用单数,因为表中的每个元组代表关系的一个对象;
    • 我使用小写字母作为表名和列名(标识符),使用大写字母作为关键字。我不喜欢数据库中的 CamelCase;
    • <table_name>_id用于 PK 列。由于表名单一,这也是可能的;
    • 我对我创建的所有约束和索引使用前缀 + 表名 + 详细信息。

    您不必遵循它们,但是为您的设计坚持一致的命名模式会非常好。

  2. 我将从property_type字典开始:

    CREATE TABLE property_type (
        property_type   varchar(20) NOT NULL,
        CONSTRAINT p_property_type PRIMARY KEY (property_type)
    );
    

    它是一个单列表,仅用于为属性类型提供可能值的域。我用过varchar(20),文字栏还不错。这样做的一个好处——你不必通过数字键加入这个表来获得什么property_type_id=123意思。

  3. 特性:

    CREATE TABLE property (
        property_id     integer     NOT NULL,
        property_name   varchar(50) NOT NULL,
        property_type   varchar(20) NOT NULL,
        CONSTRAINT p_property PRIMARY KEY (property_id),
        CONSTRAINT u_property_name UNIQUE (property_name),
        CONSTRAINT f_property_type FOREIGN KEY (property_type)
          REFERENCES property_type ON UPDATE CASCADE
    );
    

    我决定在这里使用数字 PK,因为我想您可能想在某些时候重命名属性。如果您更改property_type,更新将级联。

    尽管这里已经有一个 PK,但UNIQUE对名称的约束是必须的,否则您可能最终会遇到具有不同 ID 的相同名称属性的情况。

  4. DT 表:

    CREATE TABLE dt (
        dt_id       integer     NOT NULL,
        dt_name     varchar(50) NOT NULL,
        CONSTRAINT p_dt PRIMARY KEY (dt_id),
        CONSTRAINT u_dt_name UNIQUE (dt_name)
    );
    

    同样,只有 PK 是不够的,还会产生UNIQUE约束。虽然我会非常彻底地摆脱dt_id并且只会保留 dt_name并且会使其成为PK。

  5. DT 的属性:

    CREATE TABLE dt_property (
        dt_id           integer     NOT NULL,
        property_id     integer     NOT NULL,
        initial_value   varchar(50) NOT NULL,
        CONSTRAINT p_dt_property PRIMARY KEY (dt_id, property_id),
        CONSTRAINT f_dt_id FOREIGN KEY (dt_id) REFERENCES dt,
        CONSTRAINT f_property_id FOREIGN KEY (property_id) REFERENCES property
    );
    

    这是与您的设计的第一个重大区别——使用了复合键。

    是的,这意味着只要您想引用此表中的条目,就必须执行 2 列。但这并不是什么大问题,真的——你设计了一次表格,你也写了一次查询,但是如果你的软件做得正确并且易于维护,它可能会使用相当长的一段时间。从长远来看,最好花更多时间编写查询并轻松维护系统。

  6. 标签:

    CREATE TABLE tag (
        tag_id      integer     NOT NULL,
        tag_name    varchar(50) NOT NULL,
        CONSTRAINT p_tag PRIMARY KEY (tag_id),
        CONSTRAINT u_tag_name UNIQUE (tag_name)
    );
    

    这只是另一本字典。同样,就像dt表格一样,我真的很想避免使用tag_idcolumn 并保留 just tag_name,使其也是一个 PK。

  7. 新表tag_dt介绍:

    CREATE TABLE tag_dt (
        tag_id      integer     NOT NULL,
        dt_id       integer     NOT NULL,
        CONSTRAINT p_tag_dt PRIMARY KEY (tag_id, dt_id),
        CONSTRAINT f_tag_id FOREIGN KEY (tag_id) REFERENCES tag,
        CONSTRAINT f_dt_id FOREIGN KEY (dt_id) REFERENCES dt
    );
    

    此表是创建dt+tag关系所必需的。没有它,你就会有数据重复——你可以在你的架构上看到它,你有 2 行带有Tag_name='Tag1'.

  8. 最后,标签属性:

    CREATE TABLE tag_property (
        tag_id      integer     NOT NULL,
        dt_id       integer     NOT NULL,
        property_id integer     NOT NULL,
        a_value     varchar(50) NOT NULL,
        CONSTRAINT p_tag_property PRIMARY KEY (tag_id, dt_id),
        CONSTRAINT u_tag_property UNIQUE (tag_id, property_id),
        CONSTRAINT f_tag_property_tag FOREIGN KEY (tag_id, dt_id) REFERENCES tag_dt,
        CONSTRAINT f_tag_property_property FOREIGN KEY (dt_id, property_id)
          REFERENCES dt_property
    );
    

    该表是完整的复合键,它符合您的所有要求。主键是tag_id, dt_id并且它也是tag_dt表的外键,因此您希望能够引入以前未定义的内容。其次,tag_id, property_id是唯一的,意味着标签的属性不能重复。最后是dt_id, property_id引用dt_property表,这意味着只有允许的属性dt才会被注册。

最后的笔记

在大多数 DBMS 中,所有主键和唯一键都是通过索引实现的。此外,即使省略了键的第一列,一些 DBMS 也可以使用复合索引(多列索引)。至少PostgreSQL可以做到,这是我用得最多的。

请检查您的dttag表格,我强烈建议摆脱其中的代理键,就像property_type完成一样。

我没有创建任何额外的索引,通常我在实现数据模型并对其进行一些实际查询之后进行此练习。

另外,不要使用valueorname作为列名。这些是保留字,您可能会在您选择的 DBMS 的未来版本中产生意想不到的效果。

于 2014-10-10T21:32:24.513 回答
1

数据库设计完全没问题。

只需使用 Tag_DT 和 DT_Property 表

下面是一个示例查询

select a.id_tag,b.id_Property
from 
tag_dt a,dt_property b
where a.id_dt = b.id_dt;
于 2014-10-09T12:42:03.777 回答