首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

让SQL表条目引用同一个表中的其他ids是个好主意吗?

在数据库设计中,允许一个表中的条目引用同一表中的其他条目的ID(即自引用)是一种常见的做法,但是否是一个好主意取决于具体的应用场景和需求。以下是对这个问题的详细解答:

基础概念

自引用是指一个表中的字段(通常是外键)引用了该表中的另一个条目的主键。这种设计通常用于表示层次结构或具有父子关系的数据。

相关优势

  1. 简化数据模型:通过自引用,可以在一个表中表示复杂的层次结构,而不需要创建多个表。
  2. 提高查询效率:所有相关数据都在一个表中,减少了JOIN操作的需要,有时可以提高查询性能。
  3. 易于维护:数据的一致性和完整性更容易管理和维护。

类型与应用场景

  • 层次结构数据:如组织结构、目录系统等。
  • 递归关系:如评论系统中的回复(一个评论可以回复另一个评论)。
  • 树形结构:如文件系统中的目录和文件。

遇到的问题及原因

  1. 性能问题:深度嵌套的层次结构可能导致查询性能下降,因为需要多次递归JOIN操作。
  2. 数据完整性:自引用可能导致循环引用,破坏数据的完整性。
  3. 复杂性增加:设计和维护自引用表可能比简单的关系表更复杂。

解决方案

  1. 限制嵌套深度:通过数据库约束或应用程序逻辑限制层次结构的深度,防止过深的嵌套。
  2. 使用递归查询:利用SQL的递归公用表表达式(CTE)来处理层次数据的查询。
  3. 避免循环引用:在应用程序层面进行检查,确保不会创建循环引用。
  4. 索引优化:对自引用的字段进行适当的索引,以提高查询效率。

示例代码

假设我们有一个employees表,其中每个员工可以有一个上级(经理),这是一个典型的自引用场景。

代码语言:txt
复制
CREATE TABLE employees (
    id INT PRIMARY KEY,
    name VARCHAR(100),
    manager_id INT,
    FOREIGN KEY (manager_id) REFERENCES employees(id)
);

查询某个员工的所有下属(递归查询):

代码语言:txt
复制
WITH RECURSIVE subordinates AS (
    SELECT id, name
    FROM employees
    WHERE manager_id = ? -- 这里的?是上级员工的ID
    UNION ALL
    SELECT e.id, e.name
    FROM employees e
    INNER JOIN subordinates s ON e.manager_id = s.id
)
SELECT * FROM subordinates;

通过这种方式,可以有效地管理和查询具有层次结构的数据,同时注意避免可能的性能瓶颈和数据完整性问题。

总之,自引用设计在适当的情况下是非常有用的,但需要仔细考虑其潜在的挑战并采取相应的解决措施。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

手把手教你上手python库pydbgen(附代码、安装地址)

幸运的是,网上有许多高质量的真实数据库可用于尝试学习热门机器学习技巧。但是,从我个人的经验来看从个人经验来讲,我发现学习SQL并不是这样。...用一个简单的工具或库来生成一个包含多个表的,并且用自己选择的数据填充的大型数据库会不会很好?...它是一个轻量级的纯python库,用于生成随机有用的条目(例如名称,地址,信用卡号码,日期,时间,公司名称,职位名称,车牌号码等),并将其保存在Pandas数据框对象中,或者作为数据库文件中的SQLite...pydbgen中一种内置方法是realistic_email,它从种子名称中生成随机电子邮件IDs。你能想到在网络上使用这个吗?你不想给出真实的电子邮件ID,但是可以给出一个相似的?...有一些问题很容易想到: 我们可以将机器学习/统计建模和这个随机数据生成器集成吗? 可视化功能可以被添加到发生器中吗?

86860

事务隔离级别与MVCC (1)—mysql进阶(六十七)

不可重复读(Non-Repeatable Read) 当在同一个事务里,一条记录在其他事物被更改,导致多次查询出来的事务不一致,这种现象就是不可重复读。 场景:trx1读两次,trx2修改多次。...(你想在你修改数据的时候,其他事物帮你吧数据回滚。。) 不同的数据库厂商对sql标准不同,比如oracle就只支持read committed和serializable。...指向回滚的页面,如果指向的是delete页面,delete有一个old roll pointer会指向上一个执行的sql,也就是insert 的undo页面。...(注意:为什么这里事务200要更新别的,因为事务只有在执行delete,update,insert的时候才会分配事务id,这个id是自增的,所以我们目的是为了让他分配事务id) 此刻hero表的number...然后从版本链中挑选可见的记录,从上可以看到,版本链可见的是‘张飞’,该版本的trx_id为100,在m_ids内,所以不符合可见性,根据roll_pointer跳到下一个版本。

40720
  • mybatis 详解(五)——动态SQL建议收藏

    5、动态SQL:trim 语句   trim标记是一个格式化的标记,可以完成set或者是where标记的功能   ①、用 trim 改写上面第二点的 if+where 语句 其他的标记,就像是上面前缀中的and一样) 6、动态SQL: SQL 片段   有时候可能某个 sql 语句我们用的特别多,为了增加代码的重用性,简化代码,我们需要将这些代码抽取出来,然后使用时直接调用...-- 引用 sql 片段,如果refid 指定的不在本文件中,那么需要在前面加上 namespace --> 引用其他的 sql 片段 -->   注意:①、最好基于 单表来定义 sql 片段,提高片段的可重用性      ②、在 sql...片段中最好不要包括 where  7、动态SQL: foreach 语句   需求:我们需要查询 user 表中 id 分别为1,2,3的用户   sql语句:select * from user where

    73140

    如何管理SQL数据库

    请注意,虽然SQL被认为是标准,但大多数SQL数据库程序都有自己的专有扩展。...执行基本查询 要查看表中单个列的所有数据,请使用以下语法: SELECT column FROM table; 要查询同一个表中的多个列,请使用逗号分隔列名: SELECT column_1, column...如果您尝试在表中查找特定条目,但不确定该条目是什么,则这些条目很有用。...Asterisks(*)是表示“all”的占位符,它将查询表中的每一列: SELECT * FROM table; 百分号(%)表示零个或多个未知字符。...一个LEFT JOIN条款从“左”表,只有匹配的记录从“右”表返回所有记录。在外部JOIN子句的上下文中,左表是FROM子句中引用的表,右表是JOIN语句后引用的任何其他表。

    5.5K95

    快手面试,一直追着问我。。。

    跳表结构了解吗 回答:第一层是双向链表,会有多层来作为链表的索引。...,是原子性,隔离性和持久性的整合 追问:隔离级别有哪几种 回答:读未提交,读已提交,可重复读,序列化 追问:可重复读是是什么意思,怎么实现的 同一个事务中多次读取结果一致。...: Read View 中四个字段作用; 聚簇索引记录中两个跟事务有关的隐藏列; 那 Read View 到底是个什么东西?...img Read View 有四个重要的字段: m_ids :指的是在创建 Read View 时,当前数据库中「活跃事务」的事务 id 列表,注意是一个列表,“活跃事务”指的就是,启动了但还没提交的事务...undo 日志中,然后这个隐藏列是个指针,指向每一个旧版本记录,于是就可以通过它找到修改前的记录。

    58220

    mybatis 详解(五)------动态SQL

    5、动态SQL:trim 语句   trim标记是一个格式化的标记,可以完成set或者是where标记的功能   ①、用 trim 改写上面第二点的 if+where 语句 其他的标记,就像是上面前缀中的and一样) 6、动态SQL: SQL 片段   有时候可能某个 sql 语句我们用的特别多,为了增加代码的重用性,简化代码,我们需要将这些代码抽取出来,然后使用时直接调用...-- 引用 sql 片段,如果refid 指定的不在本文件中,那么需要在前面加上 namespace --> 引用其他的 sql 片段 -->   注意:①、最好基于 单表来定义 sql 片段,提高片段的可重用性      ②、在 sql...片段中不要包括 where  7、动态SQL: foreach 语句   需求:我们需要查询 user 表中 id 分别为1,2,3的用户   sql语句:select * from user where

    988100

    小公司工作 6 年,后面怎么走?

    在 Java 中,== 操作符和 equals() 方法用于比较两个对象: ①、==:用于比较两个对象的引用,即它们是否指向同一个对象实例。...如果两个变量引用同一个对象实例,== 返回 true,否则返回 false。 对于基本数据类型(如 int, double, char 等),== 比较的是值是否相等。...如果存在,Java 就会让新的变量引用池中的那个字符串;如果不存在,它会创建一个新的字符串,放入池中,并让变量引用它。...System.out.println(s1 == s2); // 输出 true,因为 s1 和 s2 引用的是字符串常量池中同一个对象。...②、悲观锁 悲观锁假设冲突是常见的,因此在数据处理过程中,它会主动锁定数据,防止其他事务进行修改。 可以直接使用数据库的锁机制,如行锁或表锁,来锁定被访问的数据。

    15810

    聚集索引:SQL Server 进阶 Level 3

    当请求到达您的数据库时,无论是SELECT语句还是INSERT,UPDATE或DELETE语句,SQL Server都只有三种可能的方式来访问语句中引用的表的数据: 只访问非聚集索引并避免访问表。...与非聚簇索引是一个独立的对象并占用他们自己的空间不同,聚簇索引和表是一样的。通过创建聚集索引,可以指示SQL Server将表中的行排序为索引键序列,并在将来的数据修改期间维护该序列。...因此,销售订单的所有行项目都会在SalesOrderDetail表中连续出现。 请记住以下有关SQL Server聚簇索引的附加要点: 由于聚簇索引的条目是表的行,聚集索引条目中没有书签值。...一个副本是堆版本,另一个是创建原始表(SalesOrderID,SalesOrderDetailID)上的同一个聚集索引。 这两个表都没有任何非聚集索引。...表3:检索单个产品的所有行 前两个查询大大受益于聚簇索引的存在; 第三个是大致相等的。 有时聚集索引是有害的吗? 答案是肯定的,主要与插入,更新和删除行有关。

    1.1K30

    SQL Server索引简介:SQL Server索引进阶 Level 1

    对数据库开发人员的透彻理解对于数据库开发人员来说非常重要,其中一个原因来自于所有其他原因:当SQL Server从客户端到达的请求时,SQL Server只有两种可能的方式来访问所请求的行: 它可以扫描包含数据的表中的每一行...像一个条目白皮书,SQL Server非聚簇索引中的每个条目都包含两部分: 搜索键,如姓氏 - 名字 - 中间初始。 。在SQL Server术语中,这是索引键。...书签与电话号码相同,允许SQL Server直接导航到与该索引条目对应的表中的行。 此外,SQL Server非聚簇索引条目具有一些仅内部使用的头信息,并且可能包含一些可选信息。...正如白页中的条目序列与城镇内的住宅地理序列不同;非聚簇索引中的条目序列与表中的行序列不同。索引中的第一个条目可能是表中最后一行,索引中的第二个条目可能是表中第一行。...创建索引时,SQL Server会在基础表中的每一行的索引中生成并维护一个条目(当覆盖过滤后的索引时,将会遇到此通用规则的一个例外)。

    1.5K40

    VFP的集合类,很多狐友都不还会这个数据结构

    集合中的每一个条目非常类似于数组中的每一个元素。然而,因为它们是对象,所以集合比数组有更多的用途。本文将从三个特殊的用途谈一下集合的使用。 使用集合替代数组 某些对象需要存贮一些事物的集合。...除了通过使用一个对象引用表单之外,它可能还需要知道表单中使用了哪些工具栏(这样你就可以避免对同一个工具栏的产生多个实例),表单是否加入了窗口菜单(MDI界面中用来排列窗口及拆分窗口的菜单条目,译者注),...该表单实例的数目(当同一个表单打开不止一次时),等等。...Tables('Products').Fields('ProductID').DataType 如果Tables是一个表对象的集合,并且表对象有一个字段对象的集合,并且字段对象有一个DataType属性...附录1 中就是这样的一个例子。Tables类的Init方法中通过从CoreMeta.dbf表中读取的变化的数据,添加表和字段的集合。

    89220

    解释SQL查询计划(一)

    如果查询引用多个表,则在名称空间的SQL语句中创建一条SQL语句,该语句列出表/视图/过程名列中的所有被引用表,并且对于每个单独的被引用表,该表的SQL语句列表都包含该查询的条目。...其他SQL语句操作 下面的SQL命令执行更复杂的SQL语句操作: CREATE TRIGGER: 在定义触发器的表中,无论是在定义触发器还是在提取触发器时,都不会创建SQL语句。...如果查询引用了多个表,如果它选择了表/视图/过程名称列中的任何引用表,则Filter包括SQL语句。 过滤选项是用户自定义的。 最大行选项默认为1,000。 最大值为10,000。...注意,如果一个SQL语句引用了多个表,那么它将在表的SQL语句列表中列出每个被引用的表,但只有当前选择的表在表名列中列出。 通过单击列标题,可以根据列表的任何列对表的SQL语句列表进行排序。...Location是清单中存储的每个表的相同查询。 如SQL语句详细信息例程和关系部分所述,该语句使用以下关系列出所有表。 引用外部(链接)表的查询不能被冻结。

    2.9K20

    40+个对初学者非常有用的PHP技巧(一)

    不需要任何更多的解释。 你还可以进一步改善: ? 这样做可以完成很多事情: 为同一个类文件搜索多个目录。 轻松更改包含类文件的目录,而不破坏任何地方的代码。...最好的办法是使用会话来传播(即使是在同一页面上)。想要这样做的话在每个页面上必须得有一个session_start。 ? 在你的脚本中: ? 5.让函数变得灵活 ?...当添加单一条目时,使用上面的函数。那么当添加多个条目时,就得创建另一个函数吗?NO。只要让函数变得灵活起来使之能够接受不同的参数即可。请看: ? 好了,现在同样的函数就可以接受不同类型的输出了。...发送输出给浏览器,并在同一时间做php处理并不是好主意。你见过这样的网站,它有一个Fatal error在侧边栏或在屏幕中间的方框中吗?你知道为什么会出现这种情况吗?...9.为MySQL连接设置正确的字符编码 曾碰到过unicode/utf-8字符被正确地存储在mysql表的问题,phpmyadmin也显示它们是正确的,但是当你使用的时候,你的网页上却并不能正确地显示。

    98520

    40+个对初学者非常有用的PHP技巧(一)

    不需要任何更多的解释。 你还可以进一步改善: ? 这样做可以完成很多事情: 为同一个类文件搜索多个目录。 轻松更改包含类文件的目录,而不破坏任何地方的代码。...最好的办法是使用会话来传播(即使是在同一页面上)。想要这样做的话在每个页面上必须得有一个session_start。 ? 在你的脚本中: ? 5.让函数变得灵活 ?...当添加单一条目时,使用上面的函数。那么当添加多个条目时,就得创建另一个函数吗?NO。只要让函数变得灵活起来使之能够接受不同的参数即可。请看: ? 好了,现在同样的函数就可以接受不同类型的输出了。...发送输出给浏览器,并在同一时间做php处理并不是好主意。你见过这样的网站,它有一个Fatal error在侧边栏或在屏幕中间的方框中吗?你知道为什么会出现这种情况吗?...9.为MySQL连接设置正确的字符编码 曾碰到过unicode/utf-8字符被正确地存储在mysql表的问题,phpmyadmin也显示它们是正确的,但是当你使用的时候,你的网页上却并不能正确地显示。

    89230

    高性能MySQL学习笔记

    多个客户在同意时刻可以同事读取同一个资源。 排他锁(写锁):排他的,一个写锁会阻塞其他写锁和读锁。 锁粒度 2.1 表锁 是最基本的锁策略,开销最小的策略。...REPEATABLE READ (可重复读) 该级别保证在同一个事务中多次读取同样的记录结果是一直的。该级别不能解决幻读的问题。...) 物化视图 实际上是预计计算并且存储在磁盘上的表,可以通过各种各样的策略刷新和更新 计数器表 如果应用在表中保存计算器,则在更新计数器时可能碰到并发问题,创建一个独立的表存储计数器通常是个好主意,...全文索引 查找的是文本中的关键词,而不是直接比较索引中的值 索引的优点 索引可以让服务器快速定位到表的指定位置,但这不是索引的唯一作用。...,它让mysql扫描尽可能少的页面,获取需要访问的记录了后在根据关联列在回到原表查询需要的所有列 优化sql_calc_found_rows 分页的时候,另一个常用的技巧时在limit语句中加上sql_calc_found_rows

    1.4K20

    每次面完美团,都是一把汗。。

    在传统的锁机制中,如果一个事务正在写数据,那么其他事务必须等待写事务完成才能读数据,MVCC 允许读操作访问数据的一个旧版本快照,同时写操作创建一个新的版本,这样读写操作就可以并行进行,不必等待对方完成...读已提交:每次读取数据前都生成一个 ReadView,这样就能保证每次读取的数据都是最新的。 MySQL执行语句的整个过程了解吗? 第一步,客户端发送 SQL 查询语句到 MySQL 服务器。...第三步,解析器开始对 SQL 语句进行解析,检查语句是否符合 SQL 语法规则,确保引用的数据库、表和列都存在,并处理 SQL 语句中的名称解析和权限验证。...确保在同一事务中多次读取相同记录的结果是一致的,即使其他事务对这条记录进行了修改,也不会影响到当前事务。...三分恶面渣逆袭:Java引用数据值传递示意图 引用类型的变量存储的是对象的地址,而不是对象本身。因此,引用类型的变量在传递时,传递的是对象的地址,也就是说,传递的是引用的值。 了解GC吗?

    24910

    使用大语言模型生成SQL Schema

    那些有文学倾向的人会知道,这两本书的作者(Iain Banks)是同一个人,但他在写科幻小说时使用了略有不同的笔名。 如果这本书后来由不同的出版商再次发行会怎样?...我们不使用一个大表,而是使用三个表并在需要时引用它们。一个用于作者,一个用于出版商,一个用于书籍。我们在 Authors 表中编写作者的详细信息,然后使用 外键 在 Books 表中引用它们。...因此,以下是使用数据定义语言 (DDL) 编写的Schema 表。我使用的是 MySQL 变体——令人讨厌的是,所有供应商仍然保持着略有不同的方言。 首先,是作者表。...DB Fiddle 中显示为“Query 3”,而这正是我们一直想要看到的数据: LLM 还能创建模式吗?...它还指出,由于真实世界中的供应商 SQL 之间存在差异,因此 DDL 在某些方面是“通用的”。

    23210

    MyBatis详解

    表名 LIMIT 偏移量,条目数量; SELECT 字段 FROM 表名 LIMIT 条目数量 OFFSEF 偏移量;(MySQL新特性8.0) 偏移量:起始索引。...八、高级映射 前面讲解的都是一对一的映射关系,也就是一个类(一张表)对应一个实体(对象),但实际环境中是存在一对多、多对一、多对多的关系的。...具体的类需要这样来设计,如下图,因为Student表是主表,一张表对应的是Java的一个类,所以可以在Student这个类中可以将Clazz这个类作为其成员属性。...原理:只要使用同一个SqlSession对象执行同一条DQL语句,就会走缓存。...readOnly: true:多条相同的DQL语句执行后返回的是同一个对象。性能好。但是存在多线程并发的安全问题。 false:多条相同的DQL执行后返回对象的副本。

    2K30

    Page management in InnoDB space files(4.InnoDB Space文件的页管理)

    引用区段的其他结构使用的区段描述符所在的FSP_HDR或者XDES页的页码和描述符条目本身在该页的字节offset的组合来引用区段。...代码阅读这个列表必须直到描述符结构开始前的8个字节的offset,从这读这个结构。确保list节点在任何结构中始终排在首位可能是个好主意,但是事实上并非如此。...丽日,每个带有FSP_HDR或者XDES页的区段将被放在FREE_FRAG列表中,以便区段中的剩余空闲页可以分配给其他的用途。...当使用每个表文件的空间的时候,每个表空间中的这个列表将是空的,除非表超过42个索引,因为每个索引只消耗两个文件段INODE项。 文件段INODE结构如下: ?...例如,在一个新创建的表中,唯一存在的是页面的根页面,他也是要给叶子页面,但是存在于内部的文件段中,以便它不必再以后被移动,叶文件段的INODE列表和片段数组将全部为空,内部文件段INODE列表将全部为空

    98121

    MYSQL 中间件分表是一个好主意?

    通过中间件来对MYSQL的数据进行分表是一个常见的对于大数量的解决的方案,通过中间件将应用的数据在中间层进行路由,通过路由将一张表的数据,映射到不同物理数据库上的表,通过应用设计的分片键将数据根据规则存储在不同的物理服务器上...在分表后,我们解决了单体MYSQL无法解决的一些问题,那么这是一个好主意吗? 这里且不武断的评判这是不是一个好的注意,我们看看在我们分库分表后,我们会遇到什么其他的问题。...1 数据查询的问题 上面提到,数据在分表后,是需要指定分片键来对数据进行存储和查询的,在数据查询的过程中,如果查询的语句中没有分片键的信息,那么数据查询本身是要通过扫描全体分表后,在给出数据结果的。...,分表后,数据备份中会遇到第一个挑战就是数据的备份的一致性,通过逻辑备份可以满足一致性的数据表备份的问题,但又保证不了数据备份中的性能的问题,本来就要解决数据库性能的问题,而大表在数据备份中逻辑备份保证不了性能...综上,分表本身是不是一个好主意,如果是一个系统建立之初,业务不稳定,数据量不确定的情况下,贸然采用分表的方式,可能不是适用,而在业务稳定后,再次进行改造,会解决部分上面提到的一些问题,至少那时你的分片键用哪个基本上是可以确定的

    31330

    SpringBoot整合Sharding水平分库(三)

    今天我们就来实现一下分库,并且分表,然后同样的执行保存数据和查询数据的操作。 水平分库分表 水平分库是把同一个表的数据按一定规则拆到不同的数据库中,每个库可以放在不同的服务器上。...在上面装好我们的数据库之后,我们就可以开始进行操作了。 第一步 创建数据库,我们分别在不同的两个数据库中创建相同表结构的两个表数据。...当我们把SQL发送给 Sharding 之后,Sharding 会经过五个步骤,然后给我们返回接口,这五个步骤分别是: SQL解析 SQL路由 SQL改写 SQL执行 结果归并 SQL解析:编写SQL查询的是逻辑表...SQL改写: 程序员面向的是逻辑表编写SQL, 并不能直接在真实的数据库中执行,SQL改写用于将逻辑 SQL改为在真实的数据库中可以正确执行的SQL。...Hint分片策略 Hint分片策略(HintShardingStrategy)和其他的分片策略都不一样了,这种分片策略无需配置分片键,分片键值也不再从 SQL中解析,而是由外部指定分片信息,让 SQL在指定的分库

    47240
    领券