【问题标题】:"Too many indexes on table" error when creating relationships in Microsoft Access 2010在 Microsoft Access 2010 中创建关系时出现“表上的索引过多”错误
【发布时间】:2010-12-27 23:13:37
【问题描述】:

我有一个主键为 UserID 的 tblUsers。

UserID 在许多表中用作外键。在一个表中,它用作多个字段的外键(例如 ObserverID、RecorderID、CheckerID)。

我已成功添加关系(在 MS Access 的“关系”视图中),其中我有表别名来执行每个表的多个关系:

*tblUser.UserID -> 1 到多个 -> tblResight.ObserverID

*tblUser_1.UserID -> 1 对多 -> tblResight.CheckerID

在创建了大约 25 个执行参照完整性的关系后,当我尝试添加一个额外的关系时,我收到以下错误:

"操作失败。表 'tblUsers.' 上的索引过多。删除表上的一些索引,然后重试操作。”

我运行了找到 here 的代码,它返回我在 tblUsers 上有 6 个索引。我知道每个表有 32 个索引的限制。

我是否使用了关系 GUI 错误?访问是否会在我创建关系时创建一个索引来执行引用完整性(尤其是在我运行脚本时不会出现的索引)?我有点困惑,任何帮助将不胜感激。

【问题讨论】:

  • 对我来说,25 种关系是荒谬的。在我看来,您可能有一个重复场,因此是一个非规范化结构。

标签: ms-access relationship indexing


【解决方案1】:

好的,在做了更多研究之后,我想我得到了这个问题的答案。显然,这是一个非常常见的天花板。我总结一下this post我在下面找到的:

每个表只能有 32 个“约束”。参照完整性 (RI) 的每个索引和执行都计入这 32 个。当您选择执行 RI 时,MS Access 会自动创建一个约束;您不能禁用此选项。

我通过谷歌找到的所有代码片段和东西都返回我在桌子上有六个索引(因此我感到困惑)。我没有发现/不知道的是,我的 25 个关系被计入了我的 32 个,因为我强制执行了 RI。

我对此的解决方案是将 RI 放在“低优先级”字段中(这样说让我很痛苦),并通过数据输入表单“强制执行”它。

基本上,这是我很快将访问权限迁移到 PostgreSQL 的另一个原因。

如果有人有更好的解决方法,我很乐意在这里。谢谢。

【讨论】:

  • 在这篇文章中,您似乎在使用“约束”这个词,而实际上您的意思是“索引”。 RI 创建隐藏索引,但一般来说,大多数表与其他表的关联不超过几个或三个,因此使用 PK 和 3 个外键限制,您只用完了 4 个索引,剩下 28 个. 如果您的表确实需要索引 28 个字段,那么我建议您查看您的结构,这很可能是非规范化的。
  • @David-W-Fenton:没有理由相信有 25 个以上的索引表示非规范化表。实际上,由于外键约束,规范化会导致更多索引。 OP 可以有一个包含 25 个字段的表,每个字段是 25 个不同表的外键。很容易想象出一个具有 25 个不同的独立属性的对象,这些属性都可以表示为 25 个不同表的索引,而不会“失去规范化”。如果是这样的话,你会建议如何处理这个问题?把桌子分成两个 1:1 的桌子?不是一个理想的解决方案。
【解决方案2】:

您的表具有在您定义关系时创建的隐藏索引。隐藏索引的名称以“~”字符开头。但是你发现的代码因为这个表达式而忽略了隐藏索引:

If Left(tbl.Name, 4) <> "MSys" And Left(tbl.Name, 1) <> "~" Then

你可以让 ListIndexes() 函数包含隐藏索引,方法是将该行更改为:

If Left(tbl.Name, 4) <> "MSys" Then

此外,您可以在即时窗口中使用以下语句验证表的索引总数:

? CurrentDb.TableDefs("tblUsers").Indexes.Count

【讨论】:

  • 感谢 HansUp,但这些基本上仍然给了我相同的答案,六个。在做了更多研究之后,我想我回答了我自己的问题。
【解决方案3】:

您可以通过以下方式获取所有索引的列表,包括隐藏的索引:

Sub TableListIndexes(sTableName As String, Optional bPrintFields As Boolean = False)

    'Print indexes on a table, and fields in each index.
    'Need to add a reference to Microsoft ADO Ext. [version] for DDL and Security (ADOX).

    Dim cat As New ADOX.Catalog
    Dim idxs As ADOX.Indexes
    Dim idx As ADOX.Index
    Dim col As ADOX.Column
    Dim i As Integer

    Set cat.ActiveConnection = CurrentProject.Connection
    Set idxs = cat.Tables(sTableName).Indexes
    For Each idx In idxs
        Debug.Print i, idx.Name
        If bPrintFields Then
            For Each col In idx.Columns
                Debug.Print , col
            Next
        End If
        i = i + 1
    Next

End Sub

Sub TestTableListIndexes()
    TableListIndexes "tblProject"
End Sub

这给了

0            PrimaryKey  
1            ProjectBusinessUnitID_6D55FF7827CC48648A15A8E576EF02EF  
2            ProjectDivisionID_9CAC7B9D8136467B97F9BAA7217EAC38
etc

请注意,如果表中有任何多值字段,每个字段都会有一个隐藏索引。

【讨论】:

    【解决方案4】:

    它已经很老了,但问题经常出现,并且这个线程首先出现在搜索机器中(有人告诉我;))

    解决这个问题的一个很好的方法是使用“帮助表”来链接到其他表。

    一个例子: 由于不同的原因,表格文章链接到许多其他表格。她自己也可能需要很多外键。这样的表经常会超出可能的索引。在我最大的项目中,我也确实有三四个。

    要使可能的 RI 连接/索引几乎翻倍,您可以使用一个辅助表,它与表 tblArticle 具有 1:1 的 RI 连接,仅将唯一标识符作为字段。我确实将它命名为相同的名称,而不是在它前面使用短字母 fk,就像我通常会做的那样。我们称之为 tblArticleLinker。

    每个从 tblArticle 获取外键的表,例如 Order-Position,都从 tblArticleLinker 获取其连接。 --> 你不会丢失所有这些链接的索引,只是链接表中的一个

    你唯一需要确定的是,你在保存的时候总是把key添加到linkertable中,否则无法使用Record。

    根据我的经验,这样的表格比在不同表格中拆分字段的常用方法更容易处理。在查询中,您并不特别需要帮助表(如果这样做,有时查询会更快),您可以直接链接到表。它只是不像往常那样自动完成。

    提示:同样的方法也可以用来确保用户只能使用“已发布”的记录。或仅用作硬过滤器。这有助于克服可能的软件错误,这些错误不遵循应有的逻辑。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-02-22
      • 2019-09-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-28
      • 1970-01-01
      相关资源
      最近更新 更多