Каков предпочтительный способ сохранения динамических списков в базе данных? - PullRequest
5 голосов
/ 11 сентября 2010

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

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

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

Должен ли я использовать следующую схему

Lists (Id, Name)
ListColumns (Id, ListId, Name)
ListRows (Id, ListId)
ListData(RowId, ColumnId, Value)

Хотя одна строка создаст столько строк в таблице данных списка, сколько столбцов в списке, это просто не так.

Вы справились с этой ситуацией? Как вы справились с этим в базе данных?

Ответы [ 5 ]

3 голосов
/ 11 сентября 2010

то, что вы сделали, называется EAV (модель атрибута-значения) .

Для списка из 3 столбцов и 1000 записей:

1 запись в списках 3 записи в ListColumns и 3000 записей в ListData

Это хорошо. Я не фанат создания таблиц на лету, потому что это может испортить вашу базу данных, и вам придется «генерировать» ваши SQL-запросы динамически. У меня было бы странное чувство, когда пользователи могли СОЗДАТЬ / УДАЛИТЬ / ИЗМЕНИТЬ Таблицы в моей базе данных!

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

Редактировать:

Я думаю, что вам нужна еще одна таблица под названием ListRows, которая сообщает вам, какие записи ListData принадлежат друг другу в строке!

2 голосов
/ 03 марта 2011

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

  • Давайте иметьlists таблица, содержащая список всех моих списков
  • Позволяет также иметь таблицу columns, содержащую метаданные (имена столбцов)
  • Теперь нам нужна таблица values, которая содержит столбецзначения
  • Нам также нужна таблица rows, которая содержит список всех строк, в противном случае очень трудно определить, сколько на самом деле строк

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

Подсчет всех строк в таблице

SELECT COUNT(*) FROM [rows]
JOIN [lists]
    ON [rows].list_id = [Lists].id
WHERE [Lists].name = 'Cars'

Хм, не так уж плохо, по сравнению с:

SELECT * FROM [Cars]

Вставка строки в таблицу

BEGIN TRANSACTION

DECLARE @row_id INT
DECLARE @list_id INT

SELECT @list_id = id FROM [lists] WHERE name = 'Cars'

INSERT INTO [rows] (list_id) VALUES (@list_id)
SELECT @row_id = @@IDENTITY

DECLARE @column_id INT

-- === Need one of these for each column ===
SELECT @column_id = id FROM [columns]
WHERE name = 'Make'
AND list_id = @list_id

INSERT INTO [values] (column_id, row_id, value)
VALUES (@column_id, @row_id, 'Rover')

-- === Need one of these for each column ===
SELECT @column_id = id FROM [columns]
WHERE name = 'Model'
AND list_id = @list_id

INSERT INTO [values] (column_id, row_id, value)
VALUES (@column_id, @row_id, 'Metro')
COMMIT TRANSACTION

Хм, начало становиться немного волосатым по сравнениюдо:

INSERT INTO [Cars] ([Make], [Model}) VALUES ('Rover', 'Metro')

Простые запросы

I 'Теперь мне надоело создавать утомительно сложные операторы SQL, так что, возможно, вы можете попробовать найти эквивалентные запросы для следующих операторов:

SELECT [Model] FROM [Cars] WHRE [Make] = 'Rover'

SELECT [Cars].[Make], [Cars].[Model], [Owners].[Name] FROM [Cars]
JOIN [Owners] ON [Owners].id = [Cars].owner_id
WHERE [Owners].Age > 50

SELECT [Cars].[Make], [Cars].[Model], [Owners].[Name] FROM [Cars]
JOIN [Owners] ON [Owners].id = [Cars].owner_id
JOIN [Addresses] ON [Addresses].id = [Owners].address_id
WHERE [Addresses].City = 'London'

Я надеюсь, что вы начинаете понимать ...

Короче говоря - я испытал это раньше, и я могу заверить вас, что создание базы данных внутри базы данных таким образом, безусловно, плохо.

Если вам нужно что-то сделать но самые основные запросы в этих списках (и буквально я имею в виду «Могу ли я иметь все элементы в этом списке, пожалуйста?»), Вы должны попытаться найти альтернативу.

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

1 голос
/ 03 марта 2011

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

Ваша схема правильна, и множественное число, на мой взгляд, также правильно, хотя я бы убрал случай с верблюдами и назвал бы их lists, list_columns, list_rows и list_data.

Я бы дополнительно улучшил вашу схему, пропустив таблицы rows и columns, они не имеют смысла.Просто прикрепите номер строки / столбца к каждой ячейке и сохраняйте разряженность: не беспокойтесь о хранении пустых ячеек в базе данных.Вы сохраняете возможность запрашивать / сортировать на основе строки / столбца, ваши запросы будут (возможно, очень) быстрее, потому что число list_cells будет уменьшено, и вам не нужно будет делать какие-либо сумасшедшие объединения, чтобы связать ваши данныевернуться к своей таблице.

Вот полная схема:

create table lists (
  id int primary key,
  name varchar(25) not null
);

create table list_cells (
  id int primary key,
  list_id int not null references lists(id)
    on delete cascade on update cascade,
  row int not null,
  col int not null,
  data varchar(25) not null
);
1 голос
/ 11 сентября 2010

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

Похоже, что структура или схема БД может измениться во время выполнения или по команде пользователя, так что, возможно, что-то подобное может помочь?

  • Пользователь хочет создать новый список сущностей, никогда не виденных ранее. Назовите это Компьютер.
  • Пользователь определяет атрибуты (размер экрана, CpuSpeed, AmountRAM, NumberOfCores)
  • Система позволяет пользователю создавать в пользовательском интерфейсе
  • Система обычно позволяет им всем быть строками, если только они не могут определить, когда все предоставленные значения действительно являются датами или числами.
  • сборка скриптов CREATE, выполнение их с БД.
  • вставить данные, которые пользователь определил, в эту новую таблицу.

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

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

0 голосов
/ 11 сентября 2010

Похоже, что Sharepoint уже развернут в вашей среде.

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

Потребовалось бы немного настроить, но вы могли бы вызвать веб-службы SP, чтобы CRUD данные вашего списка для вас.

Sharepoint 2010 также может предоставлять списки через OData, которые было бы просто использовать из любого приложения.

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