Может ли первый код автоматически создать реляционную таблицу с тремя первичными ключами? - PullRequest
0 голосов
/ 18 ноября 2011

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

Страница * ---- * Ссылка * ---- * Область

Что означает в тексте: • Страница имеет много ссылок • Ссылка может быть во многихстраница • Ссылка может быть во многих областях • Область может содержать много ссылок

Это означает, что, если я не ошибаюсь, потребуется 4 таблицы.3 для каждой сущности и одна реляционная таблица, которая будет содержать первичные ключи каждой сущности.

Есть ли способ создать таблицу такого типа с кодом в начале?

Спасибо,

Ответы [ 2 ]

1 голос
/ 21 ноября 2011

Архитектура

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

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

Таблица 1 : "ObjectTypes" .Эта таблица будет хранить список типов объектов, которые у вас есть.В нем будет три записи с именами «Страница», «Ссылка» и «Область».

  • ID int (идентификатор)
  • Имя nvarchar (50)

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

  • ID идентификатор bigint
  • Тип int (внешний ключ к таблице ObjectTypes.ID)
  • Имя nvarchar (200)

Таблица 3 : "ObjectRelationships" .Эта таблица представляет отношения между любыми двумя объектами любого типа.Если бы это была строгая иерархия, где объект мог бы иметь только одного родителя за раз, тогда вы могли бы фактически сделать ее временной иерархией, добавив поле отметки времени и создав представление, которое выбирает самую последнюю запись для каждого объекта.В вашем случае, поскольку у вас есть объекты, которые могут принадлежать нескольким другим объектам одновременно, строгая временная иерархия не требуется;но он также достаточно гибок, чтобы вы могли хранить для некоторых объектов одно отношение на объект и при этом иметь неповрежденную временную иерархию для подмножества типов объектов.Для двунаправленных отношений потребуются две записи, в которых поменялись местами ObjectID и RelatedObjectID.Обратите внимание, что для других архитектур также потребуются две записи, просто в двух отдельных таблицах.В качестве альтернативы, вы можете просто рассматривать одну запись как двунаправленное отношение, но это повлияет на то, как вы пишете и интерпретируете запросы.

  • ObjectID bigint (внешний ключ для объектов.Я БЫ);также рекомендовал бы кластеризованный индекс для этого поля
  • RelatedObjectID bigint (внешний ключ для Objects.ID);также рекомендовал бы рассматривать это направленное отношение как ParentObjectID или ContainerObjectID, и вы все равно можете добавить обратные отношения для двунаправленных отношений
  • [Timestamp] datetime (SQL Server datetime2 (7))

Таблицы с 4 по 2 ^ 32 : "Страницы" , "Ссылки" , "Области" и т. д. и т. д. и т. д. Каждая из этих трех или более таблиц хранит информацию, уникальную для конкретного типа объекта.Замечательная вещь в этой архитектуре заключается в том, что вам нужно добавить только одну таблицу для каждого нового типа объекта (вместе с новой записью в таблице ObjectTypes), потому что всегда есть одна таблица, в которой хранятся ваши объектные отношения.

Запрос данных

Если вы хотите найти все ссылки на странице, вы можете запросить прямые связи между страницами и ссылками, например так:

select L.* from Links L
inner join ObjectRelationships R on R.ObjectID = L.ID
where R.RelatedObjectID = @pageID;

или вы можете найти все ссылкина странице, косвенно связанной с такими областями, как:

--//view LinkRelationships = select * from Links L inner join ObjectRelationships R on R.ObjectID = L.ID
--//view AreaRelationships = select * from Areas A inner join ObjectRelationships R on R.ObjectID = A.ID

select L.* from LinkRelationships L
inner join AreaRelationships A on L.RelatedObjectID = A.ObjectID
inner join Pages P on P.ID = A.RelatedObjectID
where P.ID = @pageID;

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

select P.* from Pages P
inner join ObjectRelationships R on R.RelatedObjectID = P.ID
where R.ObjectID = @linkID;

Эта архитектура очень гибкая и очень эффективная с точки зрения дискового пространства (отлично подходит для устранения узких мест дискового ввода-вывода), но это требует от вас удобного выполнения соединений и представления отношений как различных «уровней» в иерархии, что демонстрируется представлениями * Level в примере запроса.Я на самом деле создаю эти представления, чтобы упростить запросы и сделать их более понятными.

1 голос
/ 18 ноября 2011

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

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

В-третьих, нет. То, что вы описываете, будет использовать 5 таблиц.Page, Link, Area, PageLink и LinkArea.Area не относится к Page в представленной вами модели, кроме как через Link.

EDIT: я не думаю, что вы тщательно продумали свою модель данных.Может ли область быть на многих страницах?Или Район только на одной странице?Может ли ссылка быть на обеих страницах?

РЕДАКТИРОВАТЬ: исходя из ваших комментариев, то, что вы хотите, это то.

Page *---* Link *---* Area 
 *----------------------*

Для этого требуется 6 таблиц.Страница, ссылка, область, PageLink, PageArea, AreaLink

...