SQL Server HierarchyId并存储简单的Web导航菜单

时间:2013-07-29 21:13:40

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

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

我注意到HierarchyId让我担心的主要事情是你只能有一个带HierarchyId的根节点。但是使用导航菜单,显然有多个顶级“根节点”可以生孩子。由于根节点没有订单(它们只是“/”),我们的客户端无法移动它们的顶级菜单链接。

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

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

1 个答案:

答案 0 :(得分:4)

我不认为我会担心有一个"假的"根节点 - 你显然不必显示它(在某些方法中,如果你小心查询,你甚至不必将根节点存储在数据库中)。

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

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

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

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

有三个"经典"这样做的方式:

  1. " 邻接列表" (我相信当你提到"在C#&#34中使用递归时,你所暗示的是什么;
  2. " 分层路径" (这是你用sql server hierarchy id得到的)
  3. " 嵌套集" (包含基于集合的sql方法)
  4. 其中任何一个都适用于存储分层数据 - 它们在不同类型的查询的性能和易于表示方面具有不同的权衡。

    参考文献:

    1. Trees in SQL(来自Joe Celko)
    2. Hierarchies: Convert Adjacency List to Nested Sets
    3. Improve hierarchy performance using nested sets
    4. Nested set model