sql-server - SQL Server HierarchyId 和存储简单的 Web 导航菜单

标签 sql-server database-design menu sql-server-2012

我们希望在 SQL Server 2012 中存储一个简单的 Web 导航菜单。这将为多个客户端完成,这就是我们需要存储它的原因。菜单项还需要有一个顺序,以便可以按照客户想要的方式排序。我一直在阅读 SQL Server 的 HierarchyId 数据类型,但我发现的几乎所有教程都使用员工或公司层次结构的示例,其中一个根节点位于顶部。经过几个小时的阅读和测试后,我有一种感觉,HierarchyId 可能不是简单的链接导航菜单的最佳工具。我已经厌倦了这种感觉吗?

我注意到 HierarchyId 让我担心的主要一点是你只能有一个具有 HierarchyId 的根节点。但是对于导航菜单,显然有多个顶级“根节点”可以生 child 的。由于根节点没有顺序(它们只是“/”),我们的客户将无法移动其顶级菜单链接。

因此,显而易见的选择是有一个虚拟根节点,并将所有顶级菜单链接都放在该根节点下。但根据 至 this SO question 、 marc_s 和 Jeremy 看起来似乎不寻常(或者根据 HierarchyId 的正常用法) 创建一个人工“über-root”节点,只是为了拥有多个 一级节点。通过执行这个“über-root”节点,我不也是 抛弃 SQL Server 的 GetLevel() 函数,因为 “顶级”节点现在将显示为级别 1 而不是 0?

我正在考虑采用在每行中存储 ParentId 的方法,并在 C# 中使用递归来构建菜单层次结构。我这样做会错吗? HierarchyId 数据类型真的适用于这种情况吗?我只是遗漏了一些东西?

最佳答案

我认为我不会担心有一个“虚拟”根节点 - 你显然不必显示它(并且在某些方法中,你甚至不必将根节点存储在数据库中,如果你对你的询问很谨慎)。

任何有根树都需要一个根,并且任何有根树都可以分解为单独的有根树,即

          A                
         / \
        B   C       =>   B        C
       / \   \          / \        \
      D   E   F        D   E        F

换句话说,您始终可以通过引入公共(public)根来组合多个树。

我相信您问题的核心是如何在数据库中存储分层数据。

共有三种“经典”方法:

  1. 邻接列表”(我相信这就是您提到“在 C# 中使用递归”时所暗示的内容
  2. 层次结构路径”(这是您通过 sql server 层次结构 ID 获得的内容)
  3. 嵌套集”(包含基于集合的 sql 方法)

其中任何一个都适合存储分层数据 - 它们在不同类型查询的性能和表示的方便性方面有不同的权衡。

引用文献:

  1. Trees in SQL (作者:乔·塞尔科)
  2. Hierarchies: Convert Adjacency List to Nested Sets
  3. Improve hierarchy performance using nested sets
  4. Nested set model

关于sql-server - SQL Server HierarchyId 和存储简单的 Web 导航菜单,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17934299/

相关文章:

sql - 如何将列变成行

mysql - 如果关系表可能驻留在多个数据库中,是否有必要以不同的方式设计它们?

css - 垂直导航菜单不会显示更多子类别

macos - 从OSX上Electron的Finder中删除菜单栏

c# - 从 SQL Server 一次或单独检索所有图像

python - pypyodbc:关键字 "WITH"附近的 OPENJSON 语法不正确

sql - 如何从XML列获取元素值?

sql-server - 查找表太多

database - DB2 的数据模型工具

css - webkit 浏览器隐藏 LI A(有时显示 :block) elements.