Слишком много индексов для ошибки таблицы при создании отношений в Microsoft Access 2010

У меня есть tblUsers, у которого есть первичный ключ UserID.

UserID используется в качестве внешнего ключа во многих таблицах. Внутри таблицы он используется как внешний ключ для нескольких полей (например, ObserverID, RecorderID, CheckerID).

Я успешно добавил отношения (в представлении «Отношения» MS Access), где у меня есть псевдонимы таблиц для выполнения нескольких отношений для каждой таблицы:

*tblUser.UserID -> 1 ко многим -> tblResight.ObserverID

*tblUser_1.UserID -> 1 ко многим -> tblResight.CheckerID

После создания около 25 отношений с обеспечением ссылочной целостности, когда я пытаюсь добавить еще одно, я получаю следующую ошибку:

«Операция не удалась. В таблице tblUsers слишком много индексов. Удалите некоторые индексы из таблицы и повторите попытку».

Я запустил код, который нашел здесь, и он вернул, что у меня есть 6 индексов по tblUsers. Я знаю, что существует ограничение в 32 индекса на таблицу.

Я неправильно использую графический интерфейс отношений? Создает ли доступ индекс для обеспечения ссылочной целостности каждый раз, когда я создаю связь (особенно индексы, которые не появятся при запуске сценария)? Я немного сбит с толку, любая помощь будет оценена.


person avianattackarmada    schedule 27.12.2010    source источник
comment
Для меня 25 отношений — это смешно. Мне кажется, что у вас может быть повторяющееся поле и, следовательно, денормализованная структура.   -  person David-W-Fenton    schedule 28.12.2010


Ответы (4)


Хорошо, проведя еще несколько исследований, я думаю, что получил ответ на этот вопрос. Судя по всему это очень распространенный потолок с доступом. Я резюмирую это сообщение, которое я нашел ниже:

Каждая таблица может иметь только 32 «ограничения». Каждый индекс и обеспечение ссылочной целостности (RI) учитываются в этом 32. MS Access автоматически создает ограничение, когда вы выбираете принудительное выполнение RI; вы не можете отключить эту опцию.

Все фрагменты кода и вещи, которые я нашел через Google, вернули, что у меня есть шесть индексов в таблице (и, следовательно, я запутался). Чего я не обнаружил/не знал, так это того, что мои 25 отношений были засчитаны против моих 32, потому что у меня был принудительный RI.

Мое решение состояло в том, чтобы удалить RI для полей с «более низким приоритетом» (мне больно это говорить) и «принудительно применять» его через формы ввода данных.

По сути, это еще одна причина, по которой я скоро перенесу Access на PostgreSQL.

Если у кого-то есть лучшая работа, я хотел бы здесь. Спасибо.

person avianattackarmada    schedule 28.12.2010
comment
В этом посте вы, кажется, используете слово ограничения, когда на самом деле имеете в виду индексы. RI создает скрытые индексы, но, как правило, большинство таблиц связаны не более чем с парой или тремя другими таблицами, поэтому с PK и, скажем, 3 ограничениями внешнего ключа вы израсходовали только 4 индекса, оставив 28. Если у вас есть таблица, в которой действительно нужно проиндексировать 28 полей, я бы посоветовал вам взглянуть на вашу структуру, которая вполне может быть денормализована. - person David-W-Fenton; 28.12.2010
comment
@David-W-Fenton: Нет причин полагать, что наличие более 25 индексов указывает на денормализованную таблицу. На самом деле нормализация приводит к БОЛЬШЕМУ количеству индексов из-за ограничений внешнего ключа. OP может иметь таблицу с 25 полями, каждый из которых является внешним ключом в 25 отдельных таблицах. Довольно легко придумать объект с 25 различными независимыми свойствами, которые все могут быть представлены в виде индексов в 25 различных таблицах без потери нормализации. Если это так, как бы вы предложили решить эту проблему? Разделить стол на два стола 1:1? Не идеальное решение. - person drwatsoncode; 14.01.2013

В вашей таблице есть скрытые индексы, созданные при определении отношений. Имена скрытых индексов начинаются с символа «~». Но код, который вы нашли, игнорирует скрытые индексы из-за этого выражения:

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

Вы можете сделать так, чтобы функция ListIndexes() включала скрытые индексы, изменив эту строку на эту:

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

Кроме того, вы можете проверить общее количество индексов для вашей таблицы с помощью этого оператора в окне Immediate:

? CurrentDb.TableDefs("tblUsers").Indexes.Count
person HansUp    schedule 28.12.2010
comment
Спасибо, HansUp, но все они по сути дали мне один и тот же ответ, шесть. Проведя еще несколько исследований, я думаю, что ответил на свой вопрос. - person avianattackarmada; 28.12.2010

Вы можете получить список всех индексов, включая скрытые, с помощью следующего:

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

Обратите внимание, что если в таблице есть поля с несколькими значениями, у каждого из них будет скрытый индекс.

person Brian Burns    schedule 30.09.2015

Она довольно старая, но проблема возникает очень часто, и эта ветка стоит на первом месте в поисковых машинах (мне кто-то сказал ;))

Хорошей возможностью решить эту проблему является работа с «вспомогательной таблицей» для связи с другими таблицами.

Пример: таблица Article по разным причинам связана со многими другими таблицами. Также ей может понадобиться много внешних ключей для себя. Такие таблицы очень часто попадают за пределы возможных индексов. У меня также есть три или четыре из них в моих самых больших проектах.

Чтобы почти удвоить количество возможных соединений/индексов RI, вы можете работать со вспомогательной таблицей, которая имеет соединение RI 1:1 с таблицей tblArticle только с уникальным идентификатором в качестве поля. Я называю его так же, но не с короткой буквой fk перед ним, как обычно. Назовем его tblArticleLinker.

Каждая таблица, которая получает внешний ключ от tblArticle, например Order-Position, получает соединение от tblArticleLinker. --> Вы не потеряете индекс для всех этих ссылок, только одну ссылку на Linkertable

Единственное, что вы должны убедиться, это то, что вы всегда добавляете ключ в таблицу ссылок при сохранении, иначе использовать запись невозможно.

По моему опыту, с такой таблицей гораздо проще работать, чем с обычным подходом к разделению полей в разных таблицах. В запросах вам не особенно нужна вспомогательная таблица (иногда запросы выполняются быстрее, если вы это сделаете), вы можете напрямую ссылаться на таблицу. Просто это не делается автоматически, как обычно.

Совет: Тот же подход можно использовать и для того, чтобы пользователь мог использовать только «выпущенные» записи. Или просто использовать в качестве жесткого фильтра. Это помогает преодолеть возможные программные ошибки, которые не следуют логике, которой должны.

person Hansi Meier    schedule 20.01.2017