Управление отдельной частью информации
Предполагая, что в вашей сфере бизнеса,
- Пользователь может иметь нулевые один или многие друг ;
- Друг должен первым быть зарегистрирован в качестве пользователя ; а также
- вы будете искать, и / или добавлять, и / или удалять, и / или изменять отдельные значения списка друзей ;
затем каждый конкретный элемент данных, собранный в Friendlist_IDs
многозначном столбце, представляет отдельный фрагмент информации, который имеет очень точное значение. Следовательно, указанный столбец
- влечет за собой надлежащую группу явных ограничений, и
- его значения могут быть изменены индивидуально посредством нескольких реляционных операций (или их комбинаций).
Короткий ответ
Следовательно, вы должны сохранить каждое из Friendlist_IDs
значений в (a) столбце, который принимает только одно единственное значение на строку в (b) таблице, которая представляет тип ассоциации концептуального уровня, который может иметь место между пользователями , то есть дружбу - как Я приведу пример в следующих разделах.
Таким образом, вы сможете обрабатывать (i) указанную таблицу как математическое отношение и (ii) указанный столбец как атрибут математического отношения - насколько это возможно, конечно, в MySQL и его диалекте SQL.
Почему?
Поскольку реляционная модель данных , созданная д-ром Э. Ф. Коддом , требует наличия таблиц, состоящих из столбцов, которые содержат ровно одно значение соответствующего домена или типа на строку; следовательно, объявление таблицы со столбцом, который может содержать более одного значения рассматриваемого домена или типа (1), не представляет математического отношения, а (2) не позволит получить преимущества, предложенные в вышеупомянутой теоретической структуре.
Моделирование дружеских отношений между пользователями : сначала необходимо определить правила бизнес-среды
Я настоятельно рекомендую начинать формировать базу данных, разграничивающую - прежде всего - соответствующую концептуальную схему в силу определения соответствующих бизнес-правил, которые, среди прочих факторов, должны описывать типы взаимосвязей, которые существуют между различными аспектами интереса, т.е. , применимые типы объектов и их свойства ; например:
- Пользователь в первую очередь идентифицируется его UserId
- Пользователь поочередно определяется комбинацией его или ее FirstName , LastName , Пол и рождения
- Пользователь поочередно идентифицируется его Имя
- Пользователь является Запросом нулевых один или-много Дружбы
- Пользователь является Адресат нулевой один или-много Дружбы
- Дружба в первую очередь определяется комбинацией его RequesterId и его AddresseeId
Описательная схема IDEF1X
Таким образом, я смог вывести диаграмму IDEF1X 1 , показанную на рисунке 1 , которая объединяет большинство ранее сформулированных правил:
Как показано, реквестер и адресат - это обозначения, которые выражают роли, выполняемые конкретными пользователями, которые принимают участие в данной дружбе .
Таким образом, тип сущности « Дружба » отображает тип ассоциации отношения множества ко многим (M: N), который может включать различные вхождения одного и того же типа сущности, то есть пользователя . Таким образом, это пример классической конструкции, известной как «ведомость материалов» или «взрыв деталей».
1 Определение интеграции для информационного моделирования ( IDEF1X ) - это очень рекомендуемый метод, который был принят в качестве стандарта в декабре 1993 года Национальным институтом стандартов и технологий США (NIST). Он основывается на (а) раннем теоретическом материале, автором которого является единственный создатель реляционной модели, т. Е. Доктор Э. Ф. Кодд ; (b)представление данных об отношениях между сущностями, разработанное доктором П.П. Ченом ; а также о (c) методике проектирования логических баз данных, созданной Робертом Г. Брауном.
Иллюстративный логический дизайн SQL-DDL
Затем, из диаграммы IDEF1X, представленной выше, объявление схемы DDL, подобной той, что следует, является гораздо более «естественным»:
-- You should determine which are the most fitting
-- data types and sizes for all the table columns
-- depending on your business context characteristics.
-- At the physical level, you should make accurate tests
-- to define the mostconvenient INDEX strategies based on
-- the pertinent query tendencies.
-- As one would expect, you are free to make use of
-- your preferred (or required) naming conventions.
CREATE TABLE UserProfile ( -- Represents an independent entity type.
UserId INT NOT NULL,
FirstName CHAR(30) NOT NULL,
LastName CHAR(30) NOT NULL,
BirthDate DATE NOT NULL,
GenderCode CHAR(3) NOT NULL,
Username CHAR(20) NOT NULL,
CreatedDateTime DATETIME NOT NULL,
--
CONSTRAINT UserProfile_PK PRIMARY KEY (UserId),
CONSTRAINT UserProfile_AK1 UNIQUE ( -- Composite ALTERNATE KEY.
FirstName,
LastName,
GenderCode,
BirthDate
),
CONSTRAINT UserProfile_AK2 UNIQUE (Username) -- Single-column ALTERNATE KEY.
);
CREATE TABLE Friendship ( -- Stands for an associative entity type.
RequesterId INT NOT NULL,
AddresseeId INT NOT NULL, -- Fixed with a well-delimited data type.
CreatedDateTime DATETIME NOT NULL,
--
CONSTRAINT Friendship_PK PRIMARY KEY (RequesterId, AddresseeId), -- Composite PRIMARY KEY.
CONSTRAINT FriendshipToRequester_FK FOREIGN KEY (RequesterId)
REFERENCES UserProfile (UserId),
CONSTRAINT FriendshipToAddressee_FK FOREIGN KEY (AddresseeId)
REFERENCES UserProfile (UserId)
);
Таким образом:
- каждая базовая таблица представляет отдельный тип объекта;
- каждый столбец обозначает единственное свойство соответствующего типа объекта;
- конкретный тип данных a фиксирован для каждого столбца , чтобы гарантировать, что все содержащиеся в нем значения принадлежат конкретному и четко определенному набору , будь то INT, DATETIME, CHAR и т. д .; а также
- несколько ограничений b настроены (декларативно), чтобы гарантировать, что утверждения в виде строк, сохраняемых во всех таблицах, соответствуют бизнес-правилам, определенным в концептуальной схеме.
Преимущества однозначного столбца
Как продемонстрировано, вы можете, например:
Воспользуйтесь преимуществом ссылочной целостности, обеспечиваемой системой управления базами данных (для краткости СУБД) для Friendship.AddresseeId
столбца, поскольку ограничение его как FOREIGN KEY (FK для краткости), которое делает ссылку на UserProfile.UserId
столбец, гарантирует, что каждое значение указывает на существующую строку.
Создайте составной PRIMARY KEY (PK), состоящий из комбинации столбцов (Friendship.RequesterId, Friendship.AddresseeId)
, помогая элегантно различать все INSERTed-строки и, естественно, защищать их уникальность .
Конечно, это означает, что вложение дополнительного столбца для присваиваемых системой суррогатных значений (например, столбца, настроенного с помощью свойства IDENTITY в Microsoft SQL Server или с атрибутом AUTO_INCREMENT в MySQL) и вспомогательного INDEX полностью излишни .
Ограничьте сохраняемые значения Friendship.AddresseeId
точным типом данных c (который должен соответствовать, например, типу , установленному для UserProfile.UserId
, в данном случае INT), позволяя СУБД позаботиться о соответствующей автоматической проверке.
Этот фактор также может помочь (а) использовать соответствующие функции встроенного типа и (б) оптимизировать использование дискового пространства .
Оптимизируйте извлечение данных на физическом уровне путем настройки небольших и быстрых подчиненных INDEX для Friendship.AddresseeId
столбца, поскольку эти физические элементы могут существенно помочь в ускорении запросов, которые включают указанный столбец.
Конечно, вы можете, например, расфасованные одну колонку для Friendship.AddresseeId
один, с несколькими столбцами тот , который включает в себя Friendship.RequesterId
и Friendship.AddresseeId
, или обоих.
Избегайте ненужной сложности, связанной с «поиском» отдельных значений, которые собираются вместе в одном столбце (очень вероятно, дублируются, ошибочно набраны и т. Д.), Курсом действий, который в конечном итоге замедлит функционирование вашей системы, потому что вы бы для выполнения указанной задачи приходится прибегать к ресурсо- и трудоемким нереляционным методам.
Таким образом, существует множество причин, требующих тщательного анализа соответствующей бизнес-среды, чтобы точно определить тип d каждого столбца таблицы.
Как указывалось выше, роль, которую играет разработчик базы данных, имеет первостепенное значение для наилучшего использования (1) преимуществ логического уровня, предлагаемых реляционной моделью, и (2) физических механизмов, предоставляемых выбранной СУБД.
a , b , c , d Очевидно, что при работе с платформами SQL (например, Firebird и PostgreSQL ), которые поддерживают создание DOMAIN (отличительная реляционная особенность), вы можете объявлять столбцы, которые принимают только значения, принадлежащие их соответствующим (соответствующим образом ограниченным и иногда поделился) ДОМЕНЫ.
Одна или несколько прикладных программ, совместно использующих рассматриваемую базу данных
Когда вы должны использовать arrays
в коде прикладной программы (ы) экранной базу данных, вам просто нужно , чтобы получить соответствующий набор данных (ы) в полном объеме , а затем «привязать» его (их) к относительно структуры коды или выполните связанный процесс (ы) приложения, которые должны иметь место.
Дополнительные преимущества однозначных столбцов: расширения структуры базы данных намного проще
Другое преимущество хранения AddresseeId
точки данных в ее зарезервированном и правильно типизированном столбце состоит в том, что это значительно облегчает расширение структуры базы данных, как я приведу в качестве примера ниже.
Сценарий развития: внедрение концепции статуса дружбы
Поскольку Дружеские может развиваться с течением времени , возможно , придется следить за такое явление, таким образом , вы должны (я) расширить концептуальную схему и (б) объявить еще несколько таблиц в логической разметке. Итак, давайте организуем следующие бизнес-правила, чтобы разграничить новые включения:
- Дружба занимает один-ко-многим FriendshipStatuses
- FriendshipStatus в первую очередь определяется комбинацией его RequesterId , его AddresseeId и его SpecifiedDateTime
- A User определяет ноль-один-или-много FriendshipStatuses
- A Статус классифицирует ноль-один-или-много FriendshipStatuses
- Статус главным образом идентифицируется своим StatusCode
- Статус поочередно идентифицируется по его имени
Расширенная диаграмма IDEF1X
Последовательно, предыдущая диаграмма IDEF1X может быть расширена для включения новых типов сущностей и типов взаимосвязей, описанных выше. Диаграмма, изображающая предыдущие элементы, связанные с новыми, представлена на рисунке 2 :
Логическая структура дополнения
После этого мы можем удлинить макет DDL с помощью следующих объявлений:
--
CREATE TABLE MyStatus ( -- Denotes an independent entity type.
StatusCode CHAR(1) NOT NULL,
Name CHAR(30) NOT NULL,
--
CONSTRAINT MyStatus_PK PRIMARY KEY (StatusCode),
CONSTRAINT MyStatus_AK UNIQUE (Name) -- ALTERNATE KEY.
);
CREATE TABLE FriendshipStatus ( -- Represents an associative entity type.
RequesterId INT NOT NULL,
AddresseeId INT NOT NULL,
SpecifiedDateTime DATETIME NOT NULL,
StatusCode CHAR(1) NOT NULL,
SpecifierId INT NOT NULL,
--
CONSTRAINT FriendshipStatus_PK PRIMARY KEY (RequesterId, AddresseeId, SpecifiedDateTime), -- Composite PRIMARY KEY.
CONSTRAINT FriendshipStatusToFriendship_FK FOREIGN KEY (RequesterId, AddresseeId)
REFERENCES Friendship (RequesterId, AddresseeId), -- Composite FOREIGN KEY.
CONSTRAINT FriendshipStatusToMyStatus_FK FOREIGN KEY (StatusCode)
REFERENCES MyStatus (StatusCode),
CONSTRAINT FriendshipStatusToSpecifier_FK FOREIGN KEY (SpecifierId)
REFERENCES UserProfile (UserId)
);
Следовательно, каждый раз, когда необходимо обновить Состояние данной Дружбы , Пользователям нужно будет только ВСТАВИТЬ новую FriendshipStatus
строку, содержащую:
подходящие RequesterId
и AddresseeId
ценности, взятые из соответствующей строки Friendship
;
новая и значимая StatusCode
ценность - взято из MyStatus.StatusCode
-;
точный момент ВСТАВКИ, т. е. - SpecifiedDateTime
предпочтительно с использованием серверной функции, чтобы вы могли надежно извлекать и сохранять ее; а также
SpecifierId
значение , которое будет указывать соответствующее , UserId
что вошло в новом FriendshipStatus
в систему -ideally, с помощью вашего приложения (s) точки-.
В связи с этим предположим, что MyStatus
таблица включает в себя следующие данные - со значениями PK, которые (a) удобны для конечного пользователя, программиста приложения и администратора баз данных и (b) малы и быстры с точки зрения байтов на физическом уровне реализации -:
+ ------------ + ----------- +
| StatusCode | Имя |
+ ------------ + ----------- +
| R | Запрошено |
+ ------------ + ----------- +
| A | Принято |
+ ------------ + ----------- +
| D | Отклонено |
+ ------------ + ----------- +
| Б | Bloqued |
+ ------------ + ----------- +
Таким образом, FriendshipStatus
таблица может содержать данные, как показано ниже:
+ ------------- + ------------- + --------------------- ---- + ------------ + ------------- +
| RequesterId | Адрес получателя | SpecifiedDateTime | StatusCode | SpecifierId |
+ ------------- + ------------- + --------------------- ---- + ------------ + ------------- +
| 1750 | 1748 | 2016-04-01 16: 58: 12.000 | R | 1750 |
+ ------------- + ------------- + --------------------- ---- + ------------ + ------------- +
| 1750 | 1748 | 2016-04-02 09: 12: 05.000 | A | 1748 |
+ ------------- + ------------- + --------------------- ---- + ------------ + ------------- +
| 1750 | 1748 | 2016-04-04 10: 57: 01.000 | Б | 1750 |
+ ------------- + ------------- + --------------------- ---- + ------------ + ------------- +
| 1750 | 1748 | 2016-04-07 07: 33: 08.000 | R | 1748 |
+ ------------- + ------------- + --------------------- ---- + ------------ + ------------- +
| 1750 | 1748 | 2016-04-08 12: 12: 09.000 | A | 1750 |
+ ------------- + ------------- + --------------------- ---- + ------------ + ------------- +
Как видите, можно сказать, что FriendshipStatus
таблица служит для составления временного ряда .
Соответствующие сообщения
Вы также можете быть заинтересованы в:
- Этот ответ, в котором я предлагаю базовый метод для решения общих отношений «многие ко многим» между двумя разными типами сущностей.
- Диаграмма IDEF1X, показанная на рисунке 1, иллюстрирует этот другой ответ . Обратите особое внимание на типы сущностей с именами Marriage и Progeny , потому что они являются еще двумя примерами того, как справиться с «проблемой взрыва деталей».
- Этот пост , в котором кратко обсуждается, как хранить разные фрагменты информации в одном столбце.