Использование таблицы конфигурации Single Row в базе данных SQL Server. Плохая идея?

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

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

Каким образом можно хранить эту информацию?

Примечание: моя СУБД - это SQL Server 2008, а уровень программирования реализован с помощью ASP.NET(на С#).

Ответ 1

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

Единая строка

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

Пара ключей/значений

  • положительный: добавление новых настроек не требует изменения схемы
  • положительный: схема таблицы узкая, а дополнительные строки используются для новых настроек.
  • отрицательный: каждый параметр имеет одно и то же значение по умолчанию (null/empty?)
  • отрицательный: все должно храниться как строки (т.е. nvarchar)
  • отрицательный: при работе с настройками в коде вы должны знать, какой тип является параметром, и использовать его

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

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

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

Это означает, что в таблице может существовать только одна строка, поскольку столбец бит должен иметь значение 0, но из-за уникального ограничения может быть только одна строка.

Ответ 2

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

Ответ 3

Одна строка будет работать нормально; он даже будет иметь сильные типы:

show_borders    bit
admin_name      varchar(50)
max_users       int

Одним из недостатков является то, что для добавления нового параметра требуется изменение схемы (alter table). Один из вариантов - нормализуется, где вы получаете таблицу типа:

pref_name       varchar(50) primary key
pref_value      varchar(50) 

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

Ответ 4

Лично я бы сохранил его в одной строке, если это то, что работает. Overkill хранить его в таблице SQL? вероятно, но нет никакого реального вреда в этом.

Ответ 5

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

Удобный способ хранения информации о конфигурации и/или пользовательских предпочтениях в XML. Многие СУБД поддерживают тип данных XML. Синтаксис XML позволяет вам расходовать "язык" и структуру, описывающие конфигурацию по мере развития этой конфигурации. Одним из преимуществ XML является его неявная поддержка иерархической структуры, позволяющая, например, хранить небольшие списки параметров конфигурации, не называя их нумерованным суффиксом. Возможный недостаток формата XML заключается в том, что поиск и вообще изменение этих данных не так прямолинейно, как другие подходы (ничего сложного, но не как простого/естественного)

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

EntityId     (foreign key to the "owner" of this attribute)
AttributeId  (foreign key to the "metadata" table where the attribute is defined)
StringValue  (it is often convenient to have different columns of different types
IntValue      allowing to store the various attributes in a format that befits 
              them)

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

AttributeId  (Primary Key)
Name
AttributeType     (some code  S = string, I = Int etc.)
Required          (some boolean indicating that this is required)
Some_other_fields   (for example to define in which order these attributes get displayed etc...)

Наконец EntityId позволяет идентифицировать некоторую сущность, которая "владеет" этими различными атрибутами. В вашем случае это может быть UserId или даже просто неявным, если у вас есть только одна конфигурация для управления.

Помимо того, что список возможных параметров конфигурации растет по мере развития приложения, модель EAV помещает "метаданные", то есть данные, относящиеся к самому Атрибуту, в datatables, следовательно, избегая всего жесткого кодирования столбца имена, обычно встречающиеся при сохранении параметров конфигурации в одной строке.

Ответ 6

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

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

Ответ 7

Пара ключей и значений аналогична .Net App.Config, которая может сохранять настройки конфигурации.

Итак, когда вы хотите получить значение, которое вы могли бы сделать:

SELECT value FROM configurationTable
WHERE ApplicationGroup = 'myappgroup'
AND keyDescription = 'myKey';

Ответ 8

Общим способом сделать это является наличие таблицы свойств в simmular для файла свойств. Здесь вы можете хранить все свои константы приложения или не такие постоянные вещи, которые вам просто нужно иметь.

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

property_entry_table

[id, scope, refId, propertyName, propertyValue, propertyType] 
1, 0, 1, "COMPANY_INFO", "Acme Tools", "ADMIN"  
2, 0, 1, "SHIPPING_ID", "12333484", "ADMIN"  
3, 0, 1, "PAYPAL_KEY", "2143123412341", "ADMIN"   
4, 0, 1, "PAYPAL_KEY", "123412341234123", "ADMIN"  
5, 0, 1, "NOTIF_PREF", "ON", "ADMIN"  
6, 0, 2, "NOTIF_PREF", "OFF", "ADMIN"   

Таким образом, вы можете сохранить данные, которые у вас есть, и данные, которые у вас будут в следующем году и пока не знаете:).

В этом примере ваша область действия и refId могут использоваться для всего, что вам нужно на задней панели. Поэтому, если propertyType "ADMIN" имеет область 0 refId 2, вы знаете, что это за предпочтение.

Тип свойства приходит в руки, когда когда-нибудь вам также нужно будет хранить информацию о не-admin.

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

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

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

Ответ 9

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

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

Ответ 10

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

Итак, ваша таблица будет выглядеть примерно так:

id, column_num, property_name, intValue, floatValue, charValue, dateValue
1, 1, weeks, 51, , ,
2, 2, pi, , 3.14159, , 
3, 4, FiscYearEnd, , , , 1/31/2015
4, 3, CompanyName, , , ACME, 

Он использует немного больше места, но в большинстве случаев вы используете несколько десятков атрибутов. Вы можете использовать оператор case из значения column_num, чтобы потянуть/вставить правое поле.

Ответ 11

Жаль, что я пришел, даары позже. Но в любом случае, то, что я делаю, просто и эффективно. Я просто создаю таблицу с тремя() столбцами:

ID - int (11)

name - varchar (64)

значение - текст

Что я делаю перед созданием нового столбца конфигурации, его обновления или чтения - это сериализовать "значение"! Таким образом, я уверен в типе (ну, php::))

Например:

Ь: 0; для B OOLEAN (false)

Ь: 1; для B OOLEAN ( true)

я: 1988; для I NT

s: 5: "Кадер"; для S TRING длиной 5 символов

Надеюсь, это поможет:)

Ответ 12

Введите ключевой столбец как varchar и столбец значений как JSON. 1 является числовым, тогда как "1" является строкой. true и false являются логическими. У вас также могут быть объекты.