Создание поля поиска в MS Access - лучше иметь одну или несколько исходных таблиц?

Я создаю базу данных для отслеживания наших участников Access 2010.

Основные данные хранятся в таблице с именем ParticipantMaster.

У меня есть несколько полей в ParticipantMaster, которым я хочу назначить значения поиска.

Школа (МЛК Хай, Централ Хай, Северо-Восток Хай...)

Интересы (изобразительное искусство, драма, спорт, литература....)

Цвет (красный, синий, зеленый...)

Я мог бы создать таблицу "Школа", другую таблицу "Интересы", другую таблицу "Цвет", а затем указать источник для каждой таблицы. SELECT Color.ColorName FROM Color а потом SELECT School.SchoolName FROM School а потом SELECT Interests.InterestPicker from Interest.... так я обычно делаю.

Но потом я подумал, что если бы вместо трех отдельных таблиц я мог иметь одну таблицу с именем ParticipantData с полями, названными School, Interests, Color..., и тогда мои поисковые запросы SELECT ParticipantData.School from ParticipantData, а также SELECT ParticipantData.Interests FROM ParticipantData, а также SELECT ParticipantData.Color FROM ParticipantData

Есть ли преимущества / недостатки у того или иного способа?

3 ответа

Решение

Таблица поиска, которую вы описали, была немного уникальной. Большинство людей не предложит вам сделать это.

    ParticipantData
 +-----------------------+
 | School    (text)      |
 | Color     (text)      |
 | Interests (text)      |
 +-----------------------+

То, что ниже, имеет немного больше смысла

    ParticipantData
 +-----------------------+
 | ID (AutoNumber)       |
 |-----------------------|
 | LookupType (number)   |
 | LookupValue (text)    |
 +-----------------------+

Основными недостатками одной таблицы, как это

  1. Сделать ограничения внешнего ключа действительно сложно. Например, вы хотите ограничить ParicipantMaster.Color только идентификаторами, которые соответствуют цвету LookupType, но лучшее, что вы можете сделать, это ограничить его идентификаторами, которые находятся в таблице данных участника.

  2. Становится больно, если вы хотите добавить атрибуты только к одному LookupType. Например, вы хотите добавить SchoolDistrict в LookupType школы, у вас есть куча нежелательных вариантов. (A. Разрешите школьному округу быть цветным знаком. B. Извлеките школу из таблицы поиска и исправьте весь свой код, C. Добавьте таблицу, которая ссылается на таблицу участников)

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

Я надеюсь, что вы не собираетесь искать в ваших таблицах.

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

Подход состоит из четырех таблиц:

PDLists (local to the front-end)
--------
K*PDListID        Long          
 *PDListName      Text (50)     
  CodeLen         Long          
 *UserCanEdit     Boolean [False]             
 *HasActiveCheck  Boolean [False]             

PDChoices (linked to the back-end)
---------
K*PDChoiceID  Long AUTONUMBER             
 *PDListID    Long          
  PDCode      Text (10)     
 *PDDesc      Text (255)    
 *Seq         Long          
 *IsActive    Boolean [True]

PDChoicesLocked (local to the front-end)
---------------
K*PDChoiceID  Long AUTONUMBER             
 *PDListID    Long          
  PDCode      Text (10)     
 *PDDesc      Text (255)    
 *Seq         Long          
 *IsActive    Boolean [True]              

PDFields (local to the front-end)
--------
K*PDListID    Long          
K*TblName     Text (50)     Used to enforce referential integrity for fields that use code:description pair & to restrict length of text entry
K*FldName     Text (50)     Used to enforce referential integrity for fields that use code:description pair & to restrict length of text entry

ЛЕГЕНДА: K: Основной ключ; *: Обязательное поле; [Foo]: Значение по умолчанию

PDLists

Первая таблица имеет запись для каждой таблицы поиска. CodeLen Поле (длина кода) используется для поиска, где вы хотите сохранить значимое сокращение. Например, вы бы установить CodeLen = 1 для поиска как: N: North; E: East; S: South; W: West,

Если UserCanEdit Истинно, тогда выпадающие списки сохраняются во внутренней таблице PDChoices. В противном случае они хранятся в локальной таблице PDChoicesLocked.

У меня есть вспомогательная функция, которая генерирует оператор SQL для использования в комбинированных полях. Я передаю ему PDListID, и он проверяет поля CodeLen и UserCanEdit, чтобы создать соответствующий оператор SELECT. Вспомогательная функция просто печатает это в ближайшем окне, и я копирую и вставляю его в нужное место.

PDListID   PDListName            CodeLen   UserCanEdit   HasActiveCheck
   1       Cardinal Directions      1          True          False

PDChoices / PDChoicesLocked

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

Seq Поле (sequence) используется для пользовательской сортировки вариантов. И IsActive Поле позволяет скрыть варианты в раскрывающемся списке без потери ссылочной целостности, если эти поиски используются в настоящее время.

PDChoiceID    PDListID    PDCode    PDDesc    Seq    IsActive
    1             1         N       North      1        True
    2             1         E       East       3        True
    3             1         S       South      2        True
    4             1         W       West       4        True

PDFields

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

PDListID   TblName           FieldName
   1       StreetAddresses   CardinalDirection
   1       Locations         CompassPoint

Форма раскрытия

Когда пользователи дважды щелкают на поле со списком с возможностью редактирования пользователем (т.е. UserCanEdit=True) затем загружается форма. Заголовок формы установлен в PDListName, Если CodeLen не является нулевым, тогда текстовое поле для кода поиска становится видимым. Если HasActiveCheck=True затем отображается флажок, который позволяет пользователю переключать активный статус отдельных выпадающих меню.

У меня есть пользовательская функция, которая ограничивает количество символов, которые могут быть введены в PDCode поле на основе CodeLen, Однако если CodeLen NULL, тогда я проверяю, нужно ли мне ограничивать длину PDDesc поле. Например, если тип поля поля Long, то я предполагаю, что я сохраняю PDChoiceID в поле и не ограничиваю длину PDDesc, Но если указанное поле является полем Text/Varchar, тогда я получаю длину этого поля и ограничиваю длину PDDesc соответственно.

Когда форма раскрывающихся списков закрыта, я запрашиваю поле со списком, по которому пользователь дважды щелкнул мышью, чтобы у него был немедленный доступ ко всем новым добавленным параметрам.

Резюме

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

Плюсы:

  • это гибкий; значения могут быть сохранены в вашей основной таблице несколькими способами
    • по PDChoiceID
    • по PDCode
    • по PDDesc
  • это масштабируемо; как только начальная настройка сделана, добавление новых поисков является быстрым
  • это мощно;
    • выбор может быть удален из выпадающего меню без удаления путем настройки IsActive=False
    • порядок сортировки элементов полностью настраивается
    • Вы можете предоставить интерфейс, позволяющий пользователям вносить изменения в список, не жертвуя ссылочной целостностью.

Минусы:

  • Первоначальная настройка требует больше усилий, чем два предложенных вами варианта.
  • вы не можете обеспечить ссылочную целостность на уровне базы данных; Я не рассматриваю это как главный довод "против", потому что если вы будете осторожны, вы все равно сможете обеспечить ссылочную целостность на уровне приложений

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

Другие вопросы по тегам