Как вы управляете «списками выбора» в базе данных - PullRequest
2 голосов
/ 17 сентября 2008

У меня есть приложение с несколькими объектами «списка выбора» (используется для заполнения выпадающих списков с одним выбором). Эти объекты должны быть извлечены из базы данных. Как мне сохранить эти объекты в базе данных? Должен ли я создать новую таблицу для каждого списка выбора? Есть ли лучшее решение?

Ответы [ 16 ]

6 голосов
/ 18 сентября 2008

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

CREATE TABLE PickList(
    ListName varchar(15),
    Value varchar(15),
    Display varchar(15),
    Primary Key (ListName, Display)
)

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

4 голосов
/ 18 сентября 2008

Ну, вы могли бы сделать что-то вроде этого:

PickListContent

IdList  IdPick  Text  
1       1       Apples
1       2       Oranges
1       3       Pears
2       1       Dogs
2       2       Cats

и опционально ..

PickList

Id    Description
1     Fruit
2     Pets
3 голосов
/ 18 сентября 2008

Зависит от разных вещей:

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

    Затем вы можете использовать Enum в коде и ограничение в БД. В случае локализованного отображения, поэтому вам нужно различное форматирование для каждой культуры, тогда вы можете использовать файлы XML или другие ресурсы для хранения литералов.

  • если они реляционные (например, «состояния - столицы»), я не очень убежден в любом случае ... но в последнее время я использовал для заполнения XML-файлы, ограничения базы данных и javascript. Он работает довольно хорошо и легко в БД.

  • если они не только для чтения, но редко меняются (то есть, как правило, не могут быть изменены конечным пользователем, а только каким-либо редактором или ежедневным пакетом), тогда я все равно рассмотрю возможность не сохранять их в БД ... это будет зависеть от конкретного случая.

  • в других случаях хранение в БД является способом (представьте себе теги StackOverflow ... они являются «поисковыми», но также могут быть изменены конечным пользователем) - возможно, с некоторым кэшированием, если это необходимо , Это требует некоторой осторожной блокировки, но это будет работать достаточно хорошо.

2 голосов
/ 18 сентября 2008

Я обнаружил, что создание отдельных таблиц - лучшая идея.

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

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

1 голос
/ 18 сентября 2008

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

id - identity or UUID field (I actually call the field xxx_id where xxx is the name of the table).  
name - display name of the item  
display_order - small int of order to display.  Default this value to something greater than 1  

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

Я обычно использую выбор, который упорядочивает сначала по порядку отображения, а затем по имени, чтобы вы могли упорядочить что-то в алфавитном порядке, добавляя при этом свои собственные исключения. Например, предположим, у вас есть список стран, которые вы хотите в альфа-порядке, но сначала должны быть США и Канада, а вы можете сказать "SELECT id, name FROM theTable ORDER BY display_order, name" and set the display_order value for the US as 1, Canada as 2 and all other countries as 9.

Вы можете стать более привлекательным, например, иметь флаг 'active', чтобы вы могли активировать или деактивировать параметры, или установить поле 'x_type', чтобы вы могли группировать параметры, столбец описания для использования в подсказках и т. Д. хорошо работает в большинстве случаев.

1 голос
/ 18 сентября 2008

Две таблицы. Если вы пытаетесь втиснуть все в одну таблицу, вы нарушаете нормализацию (если вам это важно). Вот примеры:

LIST
---------------
LIST_ID (PK)
NAME
DESCR


LIST_OPTION
----------------------------
LIST_OPTION_ID (PK)
LIST_ID (FK)
OPTION_NAME
OPTION_VALUE
MANUAL_SORT

Таблица списка просто описывает список выбора. Таблица опций list_ описывает каждую опцию в данном списке. Таким образом, ваши запросы всегда будут начинаться с знания того, какой список выбора вы хотите заполнить (либо по имени, либо по идентификатору), который вы присоедините к таблице параметров list_, чтобы получить все параметры. Столбец manual_sort есть на тот случай, если вы захотите применить определенный порядок, кроме имени или значения. (Кстати, всякий раз, когда я пытаюсь разместить слова «список» и «опция», связанные с подчеркиванием, окно предварительного просмотра становится немного странным. Вот почему я ставлю там пробел.)

Запрос будет выглядеть примерно так:

select
  b.option_name,
  b.option_value
from
  list a,
  list_option b
where
  a.name="States"
and
  a.list_id = b.list_id
order by
  b.manual_sort asc

Вы также захотите создать индекс для list.name, если вы думаете, что когда-нибудь будете использовать его в предложении where. Столбцы pk и fk обычно автоматически индексируются.

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

1 голос
/ 18 сентября 2008

Создать одну таблицу для списков и одну таблицу для list_options.

 # Put in the name of the list
 insert into lists (id, name) values (1, "Country in North America");

 # Put in the values of the list
 insert into list_options (id, list_id, value_text) values
   (1, 1, "Canada"),
   (2, 1, "United States of America"),
   (3, 1, "Mexico");
1 голос
/ 18 сентября 2008

Мы следовали шаблону новой таблицы для каждого списка выбора. Например:

Таблица FRUIT имеет идентификатор столбца, ИМЯ и ОПИСАНИЕ.
Значения могут включать в себя:
15000, яблоко, красный фрукт
15001, банан, желтый и вкусный
...

Если вам нужно сослаться на FRUIT в другой таблице, вы должны вызвать столбец FRUIT_ID и сослаться на значение идентификатора строки в таблице FRUIT.

0 голосов
/ 18 сентября 2008

Это хорошо послужило нам:

SQL> desc aux_values;
 Name                                      Type
 ----------------------------------------- ------------
 VARIABLE_ID                               VARCHAR2(20)
 VALUE_SEQ                                 NUMBER
 DESCRIPTION                               VARCHAR2(80)
 INTEGER_VALUE                             NUMBER
 CHAR_VALUE                                VARCHAR2(40)
 FLOAT_VALUE                               FLOAT(126)
 ACTIVE_FLAG                               VARCHAR2(1)

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

0 голосов
/ 18 сентября 2008

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

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

Производительность может быть на порядок выше, если использовать отдельные таблицы для каждой, если ваши списки очень длинные, но это, вероятно, незначительно, если ваши индексы и т. Д. Настроены правильно.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...