情况:
一家公司有许多项目
一个项目有许多标记
一个项目只属于一家公司
标记可以属于多个项目
公司必须有权使用自己的标签
例1:
database - 如何正确设计数据库的这一部分(循环引用?)-LMLPHP
在第一张图片中,公司的所有标记都可以通过projects/project_标记获得。但是,如果删除了所有项目,则公司的标记将不再可访问,因为项目标记和项目之间的链接已不存在。
标签应该以某种方式始终链接到公司,即使没有项目。
示例2(其中标记也链接到公司):
database - 如何正确设计数据库的这一部分(循环引用?)-LMLPHP
在第二幅图中,它应该可以工作,但这现在是一个“循环引用”吗???
对于这样的问题,最好的解决方法应该是什么?
外键呢?
最后的问题是:
如何为这种情况正确设置数据库/数据模型?
第二个例子中可能出现问题的例子:

companies:
id=1, name=MyCompany
id=2, name=OtherCompany

tags:
id=1, company_id=1, name=MyTag
id=2, company_id=2, name=OtherTag

projects:
id=1, company_id=1, name=MyProject

project_tag:
project_id=1, tag_id=1
project_id=1, tag_id=2 --> THIS ROW IS NOT VALID!

最后一个项目标记行无效,因为:
项目1链接到公司ID 1
标记ID 2链接到公司ID 2
更新:谢谢大家的信息!
基于接受的答案,postgresql的create查询将变成:
CREATE TABLE companies (
   id SERIAL PRIMARY KEY NOT NULL,
   name TEXT NOT NULL
);
CREATE TABLE projects (
   id SERIAL PRIMARY KEY NOT NULL,
   company_id INT NOT NULL,
   name TEXT NOT NULL,
   UNIQUE (id, company_id),
   FOREIGN KEY (company_id) REFERENCES companies (id) ON DELETE RESTRICT ON UPDATE CASCADE
);
CREATE TABLE tags (
   id SERIAL PRIMARY KEY NOT NULL,
   company_id INT NOT NULL,
   name TEXT NOT NULL,
   UNIQUE (id, company_id),
   FOREIGN KEY (company_id) REFERENCES companies (id) ON DELETE CASCADE ON UPDATE CASCADE
);
CREATE TABLE project_tag (
   id SERIAL PRIMARY KEY NOT NULL,
   company_id INT NOT NULL,
   project_id INT NOT NULL,
   tag_id INT NOT NULL,
   UNIQUE (company_id, project_id, tag_id),
   FOREIGN KEY (company_id, project_id) REFERENCES projects (company_id, id) ON DELETE CASCADE ON UPDATE CASCADE,
   FOREIGN KEY (company_id, tag_id) REFERENCES tags (company_id, id) ON DELETE CASCADE ON UPDATE CASCADE
);

测试:
-在项目标记中插入的行在同一个公司ID上被选中(否则:
拒绝)
-无法在项目标记中插入重复行
-如果删除项目,链接的项目标记行也将被删除
-如果删除了标记,则链接的项目标记行也将被删除
-如果公司在仍有项目时被删除,则删除将被拒绝(请参见项目表:在删除限制时)
-如果删除了公司(没有项目),则所有链接的标记也将被删除

最佳答案

首先,您的第二个模型是绝对正确的,并且其中没有任何循环引用。
您应该将Company_IDCompany作为f.k发送到TagsProject并使其不为空。
然后,您应该将TAG_IDProject_ID作为f.ks传输到Project_Tag中,并使它们一起成为唯一的。也不需要将Company_IDProjectTag传输到Project_Tag中(我们在前面的段落中传输了)。
现在,最后一个问题,你的最后要求是:
此行无效!
你不能用ER捕捉它。您应该编写一些函数、触发器或存储过程来捕获和控制它。
编辑:
基于@reaanb的评论和他出色的回答:here:您可以通过这种方式来控制这个约束,并且有一点冗余:

CREATE TABLE Project(
    project_id INT NOT NULL,
    company_id INT NOT NULL,
    PRIMARY KEY (project_id),
    FOREIGN KEY (company_id) REFERENCES Company (id),
    UNIQUE KEY (project_id, company_id)
);

CREATE TABLE Tag(
    tag_id INT NOT NULL,
    company_id INT NOT NULL,
    PRIMARY KEY (tag_id),
    FOREIGN KEY (company_id) REFERENCES Company (id),
    UNIQUE KEY (tag_id, company_id)
);

CREATE TABLE Project_Tags(
    id INT NOT NULL,
    company_id INT NOT NULL,
    project_id INT NOT NULL,
    tag_id INT NOT NULL,

    PRIMARY KEY (id),
    UNIQUE KEY (tag_id, project_id)

    FOREIGN KEY (project_id, company_id) REFERENCES Project (project_id, company_id),
    FOREIGN KEY (tag_id, company_id) REFERENCES Tag (tag_id, company_id),
);

10-05 22:25