gpt4 book ai didi

database - 如何正确设计数据库的这一部分(循环引用?)

转载 作者:搜寻专家 更新时间:2023-10-30 23:32:05 24 4
gpt4 key购买 nike

情况:

A company has many projects
A project has many tags

A project belongs to only 1 company
A tag can belong to multiple projects

A company must have access to its own tags

示例 1:

enter image description here

在第一张图片中,公司的所有标签都可以通过 projects/project_tag 获得。但是,如果所有项目都被删除,那么公司的标签将无法再访问,因为 project_tag 和项目之间的链接已经消失。标签应该以某种方式始终与公司相关联,即使没有项目也是如此。

示例 2(标签也链接到公司):

enter image description here

在第二张图片中,它应该可以工作,但这现在是“循环引用”吗???对于这样的问题,最好的解决方案应该是什么?那么外键呢?

问题最后是:如何针对这种情况正确设置数据库/数据模型?


第二个例子中可能出错的例子:

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!

The last project_tag row is not valid because:
project 1 is linked to company_id 1
tag_id 2 is linked to company_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
);

Tested:
- Rows inserted in project_tag are checked on the same company_id (else: denied)
- Not possible to insert duplicate rows into project_tag
- If a project is removed, the linked project_tag rows are also removed
- If a tag is removed, the linked project_tag rows are also removed
- If a company is being removed while still having projects, the removal is rejected (see projects table: ON DELETE RESTRICT)
- If a company (without projects) is removed, all linked tags are removed also

最佳答案

首先,你的第二个模型是绝对正确的,里面没有任何循环引用。

您应该将 CompanyCompany_ID 作为 F.K 传输到 TagsProject并使其成为Not Null

然后,您应该将TAG_IDProject_ID作为F.K传递给Project_Tag,并使其唯一。并且不需要将 ProjectCompany_IDTag (我们在上一段中传输的)传输到 Project_Tag.

现在,最后一个问题,您的最终要求:

THIS ROW IS NOT VALID!

无法通过 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),
);

关于database - 如何正确设计数据库的这一部分(循环引用?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48110156/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com