Создание поля поиска в 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) |
+-----------------------+
Основными недостатками одной таблицы, как это
Сделать ограничения внешнего ключа действительно сложно. Например, вы хотите ограничить ParicipantMaster.Color только идентификаторами, которые соответствуют цвету LookupType, но лучшее, что вы можете сделать, это ограничить его идентификаторами, которые находятся в таблице данных участника.
Становится больно, если вы хотите добавить атрибуты только к одному 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.