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

2024-05-21

情况:

一个公司有很多项目
一个项目有很多标签

一个项目只属于1家公司
一个标签可以属于多个项目

公司必须有权访问自己的标签

示例1:

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

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

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

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


第二个示例中可能出现问题的示例:

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!

最后一个 project_tag 行无效,因为:
项目1链接到公司 ID 1
tag_id 2链接到公司 ID 2


UPDATED:感谢大家提供的信息!

根据已接受的答案,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:
- 在project_tag中插入的行在相同的公司 ID(别的: 被拒绝)
- 无法插入复制行放入project_tag
- 如果项目被删除,链接的项目标签行也被删除
- 如果删除标签,则链接的项目标签行也被删除
- 如果公司在仍有项目的情况下被删除,则删除将被拒绝(参见项目表:删除限制)
- 如果删除公司(没有项目),所有链接的标签也会被删除


首先,您的第二个模型绝对正确,并且其中没有任何循环引用。

你应该传送Company_ID of Company as F.K to Tags and Project并做到Not Null.

然后,你应该传输TAG_ID and Project_ID as F.Ks into Project_Tag并共同打造独一无二。并且无需传输Company_ID of Project and Tag(我们在上一段中传输的)到Project_Tag.

现在,最后一个问题,您的最后一个要求怎么样:

此行无效!

You 无法通过 ER 捕获它。您应该编写一些函数、触发器或存储过程来捕获和控制它。

Edit:
基于@reaanb 的评论和他的精彩回答here https://stackoverflow.com/questions/43413488/how-do-i-ensure-integrity-between-unrelated-tables/43416765#43416765:您可以通过这种方式控制这个约束,但有一点冗余:

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),
);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何正确设计数据库的这一部分(循环引用?) 的相关文章

  • Eclipse IDE - 错误:构建路径指定执行环境 Java SE 1.7

    在 Eclipse 中 我收到一个错误 构建路径指定执行环境Java SE 1 7 工作区中没有安装与此环境严格兼容的 JRE 尝试这个 In Eclipse your project gt properties gt java build
  • 如何在 C# 中使用 Selenium WebDriver 获取当前窗口的 URL?

    在我的应用程序中 登录时 它会导航到另一个页面 现在我需要在 selenium C 中使用 WebDriver 获取新的 URL 我找不到任何函数来执行此操作 我努力了driver Url driver getLocation and dr
  • 使用 mongoimport 从 Windows 文件夹批量导入 MongoDB

    我的存档中有很多 json 文件 我需要将它们导入到 mongo 每一个操作中 我认为它可能是循环的 你对此有什么想法吗 如果您使用的是 Linux Unix shell 您可以尝试 for filename in do mongoimpo
  • 只允许在输入字段中输入数字

    我想要打开电话号码字段这个网站 http myfrugaltech com dev savoo register 只接受数字或数字 我无权编辑 HTML 代码 那么可以使用 jQuery 通过定位字段 ID 来完成此操作吗 如果可以的话 该
  • 如何使用 Typescript 将 jest.spyOn 与 React 函数组件一起使用

    我正在使用 Typescript 和 hooks 开发一个 React 应用程序 并且尝试使用 Enzyme 和 Jest 来测试功能组件 我无法使用 jest spyOn 来测试我的组件中的方法 jest spyOn 方法无法正确解析并在
  • 复杂对象上的 GroupBy(例如 List

    Using GroupBy and Count gt 1我试图在列表中查找我的类的重复实例 该类看起来像这样 public class SampleObject public string Id public IEnumerable
  • 在 JSON 对象中存储和发送原始文件数据

    我正在寻找一种方法来传输任何文件类型的原始文件数据和任何可能的内容 我的意思是文件和文件内容都是用户生成的 在 Backbone 前端中使用 xhr ajax 调用两种方式针对 Django 后端 编辑 也许问题仍然不清楚 如果您在 IDE
  • 时间复杂度和整数输入

    我遇到一个问题 要求描述以下代码的 Big O 中的计算复杂性 i 1 while i lt N i i 2 I found this https stackoverflow com questions 40066016 is time c
  • printf 右对齐括号内的数字

    我正在编写一个程序 显示数组中的所有信息 它必须以括号中的数组索引开头 例如 2 并且它们必须彼此正确对齐 如果只是数字 我知道你可以这样做 printf 10d index 但是用括号括起来会得到以下输出 1 2 10 11 当我真正希望
  • 如何获取 git 存储库中所有文件的计数?

    如何获取 git 存储库中当前所有文件的计数 您可以使用以下命令获取 git 存储库中所有跟踪文件的计数 git ls files wc l 命令分解 The git ls files命令本身打印出存储库中所有跟踪文件的列表 每行一个 Th
  • 网站可以检测您何时将 Selenium 与 chromedriver 结合使用吗?

    我一直在使用 Chromedriver 测试 Selenium 我注意到有些页面可以检测到您正在使用 Selenium 即使根本没有自动化 即使我只是通过 Selenium 使用 Chrome 手动浏览 Xephyr https en wi
  • 如何使用 Spring Security 手动注销用户?

    也许答案很简单 如何在 Spring Security 中手动注销当前登录的用户 拨打电话是否足够 SecurityContextHolder getContext getAuthentication setAuthenticated fa
  • VSTS部署IIS应用程序winrm并更改appsettings.json

    我正在使用 部署 IIS 应用程序 winrm 任务在另一台计算机上部署 IIS 应用程序 此任务部署 zip 文件 在此 zip 中有一个 appsettings json 其变量以下划线开头和结尾 我需要替换每个环境的 appsetti
  • 删除 IF ELSE 语句中的临时表

    我在这里面临僵局 问题是我必须更改使用 3 个不同临时表的过程 为了便于对话 让我们将它们命名为 temptable1 temptable2 temptable3 我无法在这里复制 粘贴整个过程 但总体思路是这样的 原始过程 procedu
  • 为什么 JDOM 的 getChild() 方法返回 null?

    我正在做一个关于 html 文档操作的项目 我想要现有 html 文档中的正文内容将其修改为新的 html 现在我正在使用 JDOM 我想在我的编码中使用 body 元素 为此 我在编码中使用了 getChild body 但它向我的程序返
  • 读取完 JSON 内容和意外标记后遇到的其他文本(在我的 json 中)

    我使用 JSON Net 创建的 json feed 遇到一些问题 当我尝试解析它时 它给了我 读取完 JSON 内容后遇到的附加文本 路径 第 17 行 位置 4 我尝试用以下方法验证它http json parser online fr
  • 有没有办法阻止 SQL Express 2008 空闲?

    我使用 SQL Express 2008 作为 Web 应用程序的后端 问题是 Web 应用程序是在工作时间使用的 因此有时在午餐或休息时间 如果 20 分钟内没有用户登录 SQL Express 将进入空闲状态模式并释放其缓存 我知道这一
  • 使用 TABLE_DATE_RANGE 时如何获取表名称

    我想使用 TABLE DATE RANGE 获取每日统计信息 如下所示 Select count tableName FROM TABLE DATE RANGE appengine logs appengine googleapis com
  • 如何将 pygame Surface 转换为 PIL 图像?

    我正在使用 PIL 来透视地变换屏幕的一部分 原始图像数据是一个 pygame Surface 需要转换为 PIL 图像 因此我发现了 pygame 的 tostring 函数就是为了这个目的而存在的 然而结果看起来很奇怪 见附图 这段代码
  • 变量前面的@是什么意思? [复制]

    这个问题在这里已经有答案了 可能的重复 参考 这个符号在 PHP 中意味着什么 https stackoverflow com questions 3737139 reference what does this symbol mean i

随机推荐