Вообще, таблица с одним полем — вполне нормальная ситуация.
Обычно такие таблицы определяют предметную область.
Примерами могут быть:
— список кодов штатов (NY, NJ, TX и т.д.)
— блеклист email адресов
— список ключевых слов
— список допустимых доменных зон
— список простых чисел (чтобы быстро проверить является ли большое число простым)
С точки зрения реляционной алгебры такая таблица является унарным отношением, обозначающим что что-то существует, т.е. например что существует такой штат или такая доменная зона.
Значения такого поля должны быть первичными ключами.
Но в вопросе именно автоинкрементный целый первичный ключ — и конкретно для него я не смог придумать оправданную с точки зрения нормального дизайна ситуацию, и не припомню чтобы я когда-то видел такую ситуацию или такую таблицу.
Здравствуйте, _FRED_, Вы писали:
_FR>Ладно, попробую подробнее описать ситуацию. Есть такое понятие, как Attribute: { Id, Name }. Разным таблицам в БД требуется ссылаться на списки аттрибутов. Например, таблица Table1 должна иметь ссылку на список аттрибутов, а таблица Table2 — ссылку на три списка атрибутов.
Давай еще подробнее. Какие объекты предметной области (какой?) моделируют эти таблицы? Что такое "список атрибутов", сколько их всего возможно.
Здравствуйте, vmpire, Вы писали:
_FR>>Существуют ли ситуации, когда в реляционной базе данных было бы оправдано (с точки зрения нормального дизайна, а не кривых требований :о)) наличие таблицы только лишь с одним полем: автоинкрементным целым, первичным ключём? V>Существуют. Например, реализация наследования в базе. V>Пример не выдуманный, отлично жил в работающей системе.
Если он жил именно в таком минимальном варианте — одно поле в базовой таблице объектов, то вам есть еще куда расти
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Здравствуйте, Sinix, Вы писали:
V>>Существуют. Например, реализация наследования в базе. S>Я тут покритикую чуть-чуть. Без деталей тяжело судить предметно, но решение кажется надуманным. Единственное общее между всеми лицами в вашем изложении — это то, что все они — люди.
Это не совсем так, но для системы это не важно
S>Правда, непонятно как быть, если появятся юридические. С таблицей IndividualsOrIncorporatedPersons выйдет ровно то же, что и с набором атрибутов — общих полей у них нет. Можно конечно завести в ссылающихся таблицах два внешних ключа с чеком, что один их них null — выглядит так же криво.
Отличная тема: предложить своё усложнение дизайна и тут же его обругать
S>А самая тоска — когда содержимое таблиц зависит от типа лица. Редко, но бывает.
Это как раз способ избежпть такой проблемы.
На концептуальном уровне общие атрибуты есть (например, контакты, участие во всяких списках рассылки...), но на физическом они находятся в других таблицах.
V>>Имея такую структуру, мы можем легко и однотипно обрабатывать все сущности. Например, добавить таблицу "адрес", ссылающуюся на "действующее лицо". S>Чего-чего? Адреса вообще-то существуют сами по себе.
Зависит от модели. Если вероятность одного адреса у разных лиц практически нулевая и не важна для системы, то адрес вполне может быть атрибутом лица, чтобы не усложнять.
S>Может, вы про табличку "ID лица/ID адреса/тип адреса"? Так её обычно денормализуют или разбивают на несколько.
Нет такой таблицы. Есть таблица адресов со ссылкой на ID того, чей это адрес. Если идентичность адресов станет важна для системы (что практически не вероятно в том случаее), то можно её разбить на две — "адреса" и "связи". Способ ссылки при этом не изменится.
S>Юр. и физлица — вообще идеальный пример влияния дырявых абстрацкий на дизайн.
Дырявые они или нет, но это реальные сущности предметной области, с которыми надо работать.
Впрочем, в примере, который я приводил, различие не в этом. Можно упрощённо считать, что там все лица физические.
Здравствуйте, _FRED_, Вы писали:
_FR>Существуют ли ситуации, когда в реляционной базе данных было бы оправдано (с точки зрения нормального дизайна, а не кривых требований :о)) наличие таблицы только лишь с одним полем: автоинкрементным целым, первичным ключём?
реестр объектов с операциями регистрация/удаление и существует/несуществует
Das Reich der Freiheit beginnt da, wo die Arbeit aufhört. (c) Karl Marx
Здравствуйте, Other Sam, Вы писали:
OS>"список атрибутов для таблицы" — это что-то УЖАСНОЕ!!! Это 100% ошибка в OS>понимании задачи. OS>... OS>не должно возникнуть необходимости заносить их в саму базу данных.
Ты еще не сталкивался с большими тиражируемыми системами-конструкторами?
Здравствуйте, vmpire, Вы писали:
V>Существуют. Например, реализация наследования в базе.
Я тут покритикую чуть-чуть. Без деталей тяжело судить предметно, но решение кажется надуманным. Единственное общее между всеми лицами в вашем изложении — это то, что все они — люди. Правда, непонятно как быть, если появятся юридические. С таблицей IndividualsOrIncorporatedPersons выйдет ровно то же, что и с набором атрибутов — общих полей у них нет. Можно конечно завести в ссылающихся таблицах два внешних ключа с чеком, что один их них null — выглядит так же криво.
А самая тоска — когда содержимое таблиц зависит от типа лица. Редко, но бывает.
V>Имея такую структуру, мы можем легко и однотипно обрабатывать все сущности. Например, добавить таблицу "адрес", ссылающуюся на "действующее лицо".
Чего-чего? Адреса вообще-то существуют сами по себе. Может, вы про табличку "ID лица/ID адреса/тип адреса"? Так её обычно денормализуют или разбивают на несколько.
Юр. и физлица — вообще идеальный пример влияния дырявых абстрацкий на дизайн.
_FR>Да ёлки-палки, какие могут быть варианты-то? Приведи ради интереса пару других, отличных
_FR>Например, есть таблица Заметки { NoteId, Note }, есть таблицы Товары, Служащие, Контракты, Адреса, … всё что угодно. Каждый Товар, Служащий, Контракт или Адрес может иметь несколько Заметок. Всё. Как?
Notes:
int content_type
varchar object_pk
text note_text
user, date, title, etc
content_type — идентификатор таблицы, на которую ссылается заметка.
Как кодировать content_type и object_pk — дело ваше.
Существуют ли ситуации, когда в реляционной базе данных было бы оправдано (с точки зрения нормального дизайна, а не кривых требований :о)) наличие таблицы только лишь с одним полем: автоинкрементным целым, первичным ключём?
Help will always be given at Hogwarts to those who ask for it.
On 04/29/2010 03:46 PM, _FRED_ wrote: > Существуют ли ситуации, когда в реляционной базе данных было бы > оправдано (с точки зрения нормального дизайна, а не кривых требований > :о)) наличие таблицы только лишь с одним полем: автоинкрементным целым, > первичным ключём?
С точки зрения нормального дизайна, я думаю, что не существует.
Скорее всего требовалось обеспечить генерацию уникальных
идентификаторов. В постгриз для этого есть sequense. В других базах тоже
бывает что-то такое.
Так вот при совпадении таких условий появление таблицы может быть
следстивем реализации.
— Необходимы уникальные значения для разных клиентов.
— Идентификаторы обязательно назначает база данных.
— использовать транзакции нельзя.
— в базе данных нет поддержки для генерации последовательностей
уникальных значений.
Вот в этих условиях может появиться такая таблица. Очевидно, что это
"кривые требования" а не "нормальный дизайн".
Здравствуйте, _FRED_, Вы писали:
_FR>Существуют ли ситуации, когда в реляционной базе данных было бы оправдано (с точки зрения нормального дизайна, а не кривых требований :о)) наличие таблицы только лишь с одним полем: автоинкрементным целым, первичным ключём?
Здравствуйте, _FRED_, Вы писали:
_FR>Существуют ли ситуации, когда в реляционной базе данных было бы оправдано (с точки зрения нормального дизайна, а не кривых требований :о)) наличие таблицы только лишь с одним полем: автоинкрементным целым, первичным ключём?
Ладно, попробую подробнее описать ситуацию. Есть такое понятие, как Attribute: { Id, Name }. Разным таблицам в БД требуется ссылаться на списки аттрибутов. Например, таблица Table1 должна иметь ссылку на список аттрибутов, а таблица Table2 — ссылку на три списка атрибутов. У меня придумалось это вот:
Здравствуйте, _FRED_, Вы писали:
_FR>Ладно, попробую подробнее описать ситуацию. Есть такое понятие, как Attribute: { Id, Name }. Разным таблицам в БД требуется ссылаться на списки аттрибутов. Например, таблица Table1 должна иметь ссылку на список аттрибутов, а таблица Table2 — ссылку на три списка атрибутов. У меня придумалось это вот:
_FR>
По-моему, таблица Attributes никакого логического смысла не несет и демонстрирует только денормализацию БД. По крайней мере я пока не могу понять, зачем ссылаться на абстрактное число, которое даже не содержит описания. Или вы таким образом пытаетесь таблички в своей БД пронумеровать?
Здравствуйте, sunsquirel, Вы писали:
_FR>>Ладно, попробую подробнее описать ситуацию. Есть такое понятие, как Attribute: { Id, Name }. Разным таблицам в БД требуется ссылаться на списки аттрибутов. Например, таблица Table1 должна иметь ссылку на список аттрибутов, а таблица Table2 — ссылку на три списка атрибутов. У меня придумалось это вот:
S>По-моему, таблица Attributes никакого логического смысла не несет и демонстрирует только денормализацию БД. По крайней мере я пока не могу понять, зачем ссылаться на абстрактное число, которое даже не содержит описания. Или вы таким образом пытаетесь таблички в своей БД пронумеровать?
Есть предложение, как по-другому сослаться из Table1 и Table2 на множества записей таблицы Attribute? А если, например, я введу поле Attributes: { Id, DummyName, } всё станет нормально? Нет? А почему?
Help will always be given at Hogwarts to those who ask for it.
On 04/29/2010 04:53 PM, _FRED_ wrote: > Здравствуйте, _FRED_, Вы писали: > > _FR>Существуют ли ситуации, когда в реляционной базе данных было бы оправдано (с точки зрения нормального дизайна, а не кривых требований :о)) наличие таблицы только лишь с одним полем: автоинкрементным целым, первичным ключём? > > Ладно, попробую подробнее описать ситуацию. Есть такое понятие, как Attribute: { Id, Name }. Разным таблицам в БД требуется ссылаться на списки аттрибутов. Например, таблица Table1 должна иметь ссылку на список аттрибутов, а таблица Table2 — ссылку на три списка атрибутов. У меня придумалось это вот: > >
> > Так вот я и призадумался — нету ли какого другого решения или, возможно, вполне нормально наличие теблицы Attributes с одним единственным полем? > > ЗЫ: перенос Attributes1Id..AttributesNId из Table2 в отдельную таблицу обсуждать тут не хочу: "не сыпьте соль на рану"
Что-то страшное вы описываете.
Как понимать выражение "таблица ссылается на список атрибутов"???
Если уж нужно привязать именно к таблице какой-то набор данных
(атрибутов), используйте полное имя таблицы в качестве "внешнего ключа"
(в кавычках, потому что "это" не является внешним ключом).
Вот пример первые три таблицы определяют атрибуты и наборы атрибутов
(многие-ко-многим), последняя таблица связь Имя Таблицы и Наборы
Атрибутов (тоже многие-ко-многим).
On 04/29/2010 08:02 PM, Other Sam wrote: > Что-то страшное вы описываете.
Забыл сказать...
Информация о структуре таблицы, о ее назначении... вообще обо всем что
связанно с таблицей доступно во время разработки программы. Поэтому
"список атрибутов для таблицы" — это что-то УЖАСНОЕ!!! Это 100% ошибка в
понимании задачи.
У таблицы могут быть какие-то "атрибуты", но они должны быть такими,
чтобы можно было записать их на листочек и повешать на стену в офисе. И
не должно возникнуть необходимости заносить их в саму базу данных.
Цель — шарить один и тот пресет между несколькими сущностями, так? Других вариантов что-то не вижу.
Можно в табличке Attributes (я бы обозвал как AttributeSets или AttributePresets) добавить кучу булевых полей (ReferrableByTable1, ReferrableByTable2...) — для сценариев "пресет такой-то может быть назначен таблице такой-то и другой-то". Хоть какая-то польза будет.
Будут грабли с неочевидными зависимостями — помним "и я подумал — а зачем мне два диска c:?" Может, можно обойтись без шаринга?
P.S. Если атрибутов мало, можно извратиться — назначаем каждому атрибуту ID = степени двойки, храним в ссылающемся поле bitmask — вуаля
P.P.S. Если пресеты важны как самостоятельные сущности, изврат ничем не поможет, зато вынесет мозг саппорту.
Здравствуйте, Other Sam, Вы писали:
OS>Вот пример первые три таблицы определяют атрибуты и наборы атрибутов OS>(многие-ко-многим), последняя таблица связь Имя Таблицы и Наборы OS>Атрибутов (тоже многие-ко-многим).
В оригинальной постановке задачи Attribute_to_Set явно лишний — каждый атрибут входит строго в одни набор. У наборов нет SetData
OS>Что-то страшное вы описываете.
Так вы описали практически то же самое.
*подозрительно: доктор, а откуда у вас такие картинки?
** EAVом попахивает.
On 04/29/2010 08:15 PM, wildwind wrote: > OS>"список атрибутов для таблицы" — это что-то УЖАСНОЕ!!! Это 100% ошибка в > OS>понимании задачи. > OS>... > OS>не должно возникнуть необходимости заносить их в саму базу данных. > > Ты еще не сталкивался с большими тиражируемыми системами-конструкторами?
Если необходимо чтобы в системе было неизвестное кол-во таблиц с
неизвестными столбцами и неизвестными "атрибутами", то в реляционной
базе так и нужно сделать.
CREATE TABLE MyAppTables();
CREATE TABLE MyAppColumns();
CREATE TABLE MyAppTableAttributes();
CREATE TABLE MyAppTableAttributeSets();
-- и еще таблицы связей
Вот и все. Структура базы данных в процессе эксплуатации не изменяется.
_FRED_ пишет:
> Существуют ли ситуации, когда в реляционной базе данных было бы > оправдано (с точки зрения нормального дизайна, а не кривых требований > :о)) наличие таблицы только лишь с одним полем: автоинкрементным целым, > первичным ключём?
Нет. У такой таблицы нет атрибутов, только первичный ключ. Значит, нет данных.
Таблица бесполезна.
Здравствуйте, _FRED_, Вы писали:
_FR>Существуют ли ситуации, когда в реляционной базе данных было бы оправдано (с точки зрения нормального дизайна, а не кривых требований :о)) наличие таблицы только лишь с одним полем: автоинкрементным целым, первичным ключём?
Существуют. Например, реализация наследования в базе.
Пример: базовый класс: действующее лицо системы (живёт в таблице с одной автоинкрементной колонкой)
Дочерние классы: поставщик (таблица "поставщик", ссылается на действующее лицо),потребитель (таблица "потребитель", ссылается на действующее лицо), менеджер (таблица "менеджер ", ссылается на действующее лицо) и так далее.
Имея такую структуру, мы можем легко и однотипно обрабатывать все сущности. Например, добавить таблицу "адрес", ссылающуюся на "действующее лицо".
Пример не выдуманный, отлично жил в работающей системе.
Здравствуйте, Коваленко Дмитрий, Вы писали:
КД>Здравствуйте, vmpire, Вы писали:
_FR>>>Существуют ли ситуации, когда в реляционной базе данных было бы оправдано (с точки зрения нормального дизайна, а не кривых требований :о)) наличие таблицы только лишь с одним полем: автоинкрементным целым, первичным ключём? V>>Существуют. Например, реализация наследования в базе. V>>Пример не выдуманный, отлично жил в работающей системе.
КД>Если он жил именно в таком минимальном варианте — одно поле в базовой таблице объектов, то вам есть еще куда расти
А конструктивные соображения есть или так, высказаться захотелось?
Здравствуйте, vmpire, Вы писали:
V>>>Пример не выдуманный, отлично жил в работающей системе.
КД>>Если он жил именно в таком минимальном варианте — одно поле в базовой таблице объектов, то вам есть еще куда расти V>А конструктивные соображения есть или так, высказаться захотелось?
По теме топика? Специально посмотрел в стуктуру одной специализированной таблицы ... увы там два поля. Целочисленный первичный ключ+целочисленный идентификатор типа. На первичный ключ есть ссылки из бругих таблиц.
Не, ну можно было конечно упаковать в одно поле. Но такая экономия обычно выливается в виде больших неприятностей.
---
По теме "реализация наследования в базе" — воспользуйся поиском, я (кажется) приводил здесь описания базовой таблицы объектов, которая эксплуатировалась в нашей базе данных. И что там вокруг неё было навешано — тоже. Лет шесть или семь назад.
---
Таблиц с одним полем, лично я как-то не видел и не вижу в них особого смысла (если не считать таблиц для тестирования). Возможно для создания каких-то подмножеств... Типа есть таблица с кучей записей. А в нашей "одноколоночной" таблице мы храним ID-ы тех, которые удовлетворяют какому-то критерию. Но и то — критериев может много. Не будет же для каждого делать свою таблицу? Значит у нас будет уже таблица с двумя колонками — ID-критерия и ID-объекта.
По мне нормальная таблица — это "сурогатный" (целочисленный) первичный ключ+данные.
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Здравствуйте, _FRED_, Вы писали:
_FR>Существуют ли ситуации, когда в реляционной базе данных было бы оправдано (с точки зрения нормального дизайна, а не кривых требований :о)) наличие таблицы только лишь с одним полем: автоинкрементным целым, первичным ключём?
Пришел на ум такой случай: если нужно, чтобы разнотипные объекты (хранящиеся в разных таблицах) использовали одно пространство идентификаторов.
Здравствуйте, Коваленко Дмитрий, Вы писали:
КД>Здравствуйте, vmpire, Вы писали:
V>>>>Пример не выдуманный, отлично жил в работающей системе.
КД>>>Если он жил именно в таком минимальном варианте — одно поле в базовой таблице объектов, то вам есть еще куда расти V>>А конструктивные соображения есть или так, высказаться захотелось? КД>По теме топика?
... КД>По теме "реализация наследования в базе"
...
Нет, по теме "есть куда расти". Если по вашему данный дизайн откровенно неграмотен и свойственен необученным школьникам — извольте аргументировать.
Здравствуйте, _FRED_, Вы писали:
_FR>Существуют ли ситуации, когда в реляционной базе данных было бы оправдано (с точки зрения нормального дизайна, а не кривых требований :о)) наличие таблицы только лишь с одним полем: автоинкрементным целым, первичным ключём?
иногда нужна последовательность целых чисел в заданном диапазоне.
если в сервере получить такую последовательность нельзя, то существование такой таблицы может быть полезно.
Здравствуйте, _FRED_, Вы писали:
_FR>Существуют ли ситуации, когда в реляционной базе данных было бы оправдано (с точки зрения нормального дизайна, а не кривых требований :о)) наличие таблицы только лишь с одним полем: автоинкрементным целым, первичным ключём?
Попробую ещё раз объяснить: никакие фиктивные счётчики мне не нужны: есть отношение Master-Details. Делается оно обычно так: в таблице Details заводится поле MasterId и создаётся foreign key от этого поля на primary key таблицы Master. У меня же такая ситуация, что одни и те же Details в качестве Master могут иметь различные таблицы БД (Master1, Master2). Заводить зоопарк Master1Id, Master2Id и т.п. мне кажется не разуным.
Что я сделал: добавил таблицу DetailsList с одним единственным полем DetailsListId и в таблицу Details добавил колонку DetailsListId, которая ссылается за поле из таблицы DetailsList. Теперь из каждой таблицы, в которой требуется иметь Details я ссылаюсь на DetailsListId, по которому хранится набор необходимых дочерних записей.
Так вот интересует: не изобретаю ли я велосипед, и нет ли для моей ситуации более проверенного решения. А ситуация, говоря кратко, такая — надо получить отношения многие:к-одному между таблицей Details ("многие") и большим количеством других таблиц БД.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, vmpire, Вы писали:
_FR>>Существуют ли ситуации, когда в реляционной базе данных было бы оправдано (с точки зрения нормального дизайна, а не кривых требований :о)) наличие таблицы только лишь с одним полем: автоинкрементным целым, первичным ключём? V>Существуют. Например, реализация наследования в базе. V>Пример: базовый класс: действующее лицо системы (живёт в таблице с одной автоинкрементной колонкой) V>Дочерние классы: поставщик (таблица "поставщик", ссылается на действующее лицо),потребитель (таблица "потребитель", ссылается на действующее лицо), менеджер (таблица "менеджер ", ссылается на действующее лицо) и так далее. V>Имея такую структуру, мы можем легко и однотипно обрабатывать все сущности. Например, добавить таблицу "адрес", ссылающуюся на "действующее лицо". V>Пример не выдуманный, отлично жил в работающей системе.
ИМХО, для описанного сценария больше подойдёт агрегирование, в котором таблица с одной колонкой будет не нужна.
Help will always be given at Hogwarts to those who ask for it.
On 05/04/2010 02:00 PM, _FRED_ wrote: > > Попробую ещё раз объяснить: никакие фиктивные счётчики мне не нужны: > есть отношение Master-Details. Делается оно обычно так: в таблице > Details заводится поле MasterId и создаётся foreign key от этого поля на > primary key таблицы Master. У меня же такая ситуация, что одни и те же > Details в качестве Master могут иметь различные таблицы БД (Master1, > Master2). Заводить зоопарк Master1Id, Master2Id и т.п. мне кажется не > разуным. > > Что я сделал: добавил таблицу DetailsList с одним единственным полем > DetailsListId и в таблицу Details добавил колонку DetailsListId, которая > ссылается за поле из таблицы DetailsList. Теперь из каждой таблицы, в > которой требуется иметь Details я ссылаюсь на DetailsListId, по которому > хранится набор необходимых дочерних записей. > > Так вот интересует: не изобретаю ли я велосипед, и нет ли для моей > ситуации более проверенного решения. А ситуация, говоря кратко, такая — > надо получить отношения многие:к-одному между таблицей Details > ("многие") и большим количеством других таблиц БД.
Здравствуйте, _FRED_, Вы писали:
_FR>Так вот интересует: не изобретаю ли я велосипед, и нет ли для моей ситуации более проверенного решения.
Есть конечно, и не одно. Чтобы предложить подходящее, нужно прояснить твою ситуацию.
_FR>А ситуация, говоря кратко, такая — надо получить отношения многие:к-одному между таблицей Details ("многие") и большим количеством других таблиц БД.
Повторяю свой вопрос: какие объекты предметной области (какой?) моделируют эти таблицы? Также неплохо привести текущую схему (ER).
Излишняя абстракция рождает непонимание.
Здравствуйте, wildwind, Вы писали:
_FR>>Так вот интересует: не изобретаю ли я велосипед, и нет ли для моей ситуации более проверенного решения. W>Есть конечно, и не одно. Чтобы предложить подходящее, нужно прояснить твою ситуацию.
_FR>>А ситуация, говоря кратко, такая — надо получить отношения многие:к-одному между таблицей Details ("многие") и большим количеством других таблиц БД. W>Повторяю свой вопрос: какие объекты предметной области (какой?) моделируют эти таблицы? Также неплохо привести текущую схему (ER). W>Излишняя абстракция рождает непонимание.
Да ёлки-палки, какие могут быть варианты-то? Приведи ради интереса пару других, отличных
Например, есть таблица Заметки { NoteId, Note }, есть таблицы Товары, Служащие, Контракты, Адреса, … всё что угодно. Каждый Товар, Служащий, Контракт или Адрес может иметь несколько Заметок. Всё. Как?
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>Например, есть таблица Заметки { NoteId, Note }, есть таблицы Товары, Служащие, Контракты, Адреса, … всё что угодно. Каждый Товар, Служащий, Контракт или Адрес может иметь несколько Заметок. Всё. Как?
Для такого сценария — по отдельной табличке типа OrderNodes, CustomerNodes etc (ID, %ParentTableName%_ID, Note).
Для сценария, когда надо шарить один и тот же список между несколькими сущностями — ваш вариант.
Здравствуйте, Sinix, Вы писали:
_FR>>Например, есть таблица Заметки { NoteId, Note }, есть таблицы Товары, Служащие, Контракты, Адреса, … всё что угодно. Каждый Товар, Служащий, Контракт или Адрес может иметь несколько Заметок. Всё. Как? S>Для такого сценария — по отдельной табличке типа OrderNodes, CustomerNodes etc (ID, %ParentTableName%_ID, Note).
А какой поинт в том, что бы дублировать структуру таблицы Notes? Я бы ещё немного понял таблицу OrderNodes (Id, OrderId, NoteId) и так далее, но это мне всё равно не нравится: количество таблиц увеличивается вдвое, причём половина таблиц имеет одинаковую структуру.
S>Для сценария, когда надо шарить один и тот же список между несколькими сущностями — ваш вариант.
Нет, списки шарить не нужно. Но, например, Адрес может иметь несколько наборов заметок: Заметки-об-адресе-в-целом, заметки-о-городе, заметки-об-индексе, заметки-об-улице…
Help will always be given at Hogwarts to those who ask for it.
> _FR>>Например, есть таблица Заметки { NoteId, Note }, есть таблицы > Товары, Служащие, Контракты, Адреса, … всё что угодно. Каждый Товар, > Служащий, Контракт или Адрес может иметь несколько Заметок. Всё. Как? > S>Для такого сценария — по отдельной табличке типа OrderNodes, > CustomerNodes etc (ID, %ParentTableName%_ID, Note). > > А какой поинт в том, что бы дублировать структуру таблицы Notes? Я бы > ещё немного понял таблицу OrderNodes (Id, OrderId, NoteId) и так далее, > но это мне всё равно не нравится: количество таблиц увеличивается вдвое, > причём половина таблиц имеет одинаковую структуру. > > S>Для сценария, когда надо шарить один и тот же список между несколькими > сущностями — ваш вариант. > > Нет, списки шарить не нужно. Но, например, Адрес может иметь несколько > наборов заметок: Заметки-об-адресе-в-целом, заметки-о-городе, > заметки-об-индексе, заметки-об-улице…
В вашем случае, чтобы получить 3ю нормальную форму придется делать так.
Здравствуйте, _FRED_, Вы писали:
_FR>А какой поинт в том, что бы дублировать структуру таблицы Notes?
Те же, что и для любой нормализации.
Упрощаются запросы, работает быстрее (слегка), больше покрываемых юз-кейсов (например, легко можно выбрать все заметки заказчиков), проще в саппорте, исключаются сценарии дублирования — когда одна заметка навешена нескольким элементам, не смешиваются различные сущности.
Но это — когда данные обрабатываются влияют на БЛ. Если "только для показать" — лучше EAV'ом (псевдокод)-
+ check на (TableObject_ID, TableColumn_ID, Table_ID).
_FR>Нет, списки шарить не нужно. Но, например, Адрес может иметь несколько наборов заметок: Заметки-об-адресе-в-целом, заметки-о-городе, заметки-об-индексе, заметки-об-улице…
Ухх... Нда, это вообще оверкил выходит. Возвращаемся к чему пришли.
Здравствуйте, _FRED_, Вы писали:
_FR>Например, есть таблица Заметки { NoteId, Note }, есть таблицы Товары, Служащие, Контракты, Адреса, … всё что угодно. Каждый Товар, Служащий, Контракт или Адрес может иметь несколько Заметок. Всё. Как?
А чем тут поможет еще одна таблица с ID заметок? Может сразу ссылаться на записи в таблице заметок?
Если количество заметок динамично для каждой сущности, то проще сделать через дополнительную таблицу для связи многие-ко-многим: EntitiesNotes (EntityId, EntityType, NoteId), где EntityType задается через where в селекте. Или чтобы отношения между таблицами не перекладывать на программистов, сделать по одному полю на каждый тип объектов: EntitiesNotes (ProductId, EmployeeId, ..., NoteId). Но тут неудобство в создании первичного ключа — надо вводить суррогатные NULL, плюс пересоздавать ключ при введении дополнительной сущности.
Здравствуйте, Donz, Вы писали:
_FR>>Например, есть таблица Заметки { NoteId, Note }, есть таблицы Товары, Служащие, Контракты, Адреса, … всё что угодно. Каждый Товар, Служащий, Контракт или Адрес может иметь несколько Заметок. Всё. Как?
D>А чем тут поможет еще одна таблица с ID заметок? Может сразу ссылаться на записи в таблице заметок?
D>Если количество заметок динамично для каждой сущности, то проще сделать через дополнительную таблицу для связи многие-ко-многим: EntitiesNotes (EntityId, EntityType, NoteId), где EntityType задается через where в селекте. Или чтобы отношения между таблицами не перекладывать на программистов, сделать по одному полю на каждый тип объектов: EntitiesNotes (ProductId, EmployeeId, ..., NoteId). Но тут неудобство в создании первичного ключа — надо вводить суррогатные NULL, плюс пересоздавать ключ при введении дополнительной сущности.
Вот как раз "безымянных" "EntityId, EntityType" избежать и пытаюсь. А так же созданием на каждую таблицу отдельного поля — сиквелу будет казаться, что от нотесов до какой-либо таблицы ведёт более одного пути (например, если между ProductId и EmployeeId есть связь).
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, Sinix, Вы писали:
_FR>>А какой поинт в том, что бы дублировать структуру таблицы Notes? S>Те же, что и для любой нормализации. S>Упрощаются запросы, работает быстрее (слегка), больше покрываемых юз-кейсов (например, легко можно выбрать все заметки заказчиков), проще в саппорте, исключаются сценарии дублирования — когда одна заметка навешена нескольким элементам, не смешиваются различные сущности.
По сравнению с чем? С тем вариантом, что у меня сейчас? Да и в принципе, редко замечал, что нормализация приводит к упрощению запросов более быстрой работе чего-то там.
S>Но это — когда данные обрабатываются влияют на БЛ. Если "только для показать" — лучше EAV'ом (псевдокод)- S>+ check на (TableObject_ID, TableColumn_ID, Table_ID).
Нет, "безымянных" решений не хочется. Связи хочу иметь явные, простые и понятные. Не хватало ещё вркопашную следить за ссылочной целостностью.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>Нет, "безымянных" решений не хочется. Связи хочу иметь явные, простые и понятные. Не хватало ещё вркопашную следить за ссылочной целостностью.
Вам всё равно придётся следить за тем, чтобы разным сущностям не был назначен один и тот же список заметок. Любое денормализованное решение будет подвержено уязвимостям обновления. Либо смягчать инварианты, либо баш-на-баш по производительности.
Здравствуйте, Sinix, Вы писали:
_FR>>Нет, "безымянных" решений не хочется. Связи хочу иметь явные, простые и понятные. Не хватало ещё вркопашную следить за ссылочной целостностью. S>Вам всё равно придётся следить за тем, чтобы разным сущностям не был назначен один и тот же список заметок. Любое денормализованное решение будет подвержено уязвимостям обновления. Либо смягчать инварианты, либо баш-на-баш по производительности.
Это меня волнует мало, ибо высокоуровневой операции "назначении списка заметок" не будет (списки заметок будут создаваться сразу при создании сужности, а потом будут делаться только изменения таблицы Notes), а защищаться от того, что кто-то руками станет менять таблицы бессмысленно.
Интересно было бы узнать, какие проблемы могут быть из-за того, что у меня, по-сути, связь от родительской таблицы к детям, а не наоборот.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>>>Существуют ли ситуации, когда в реляционной базе данных было бы оправдано (с точки зрения нормального дизайна, а не кривых требований :о)) наличие таблицы только лишь с одним полем: автоинкрементным целым, первичным ключём? V>>Существуют. Например, реализация наследования в базе. V>>Пример: базовый класс: действующее лицо системы (живёт в таблице с одной автоинкрементной колонкой) V>>Дочерние классы: поставщик (таблица "поставщик", ссылается на действующее лицо),потребитель (таблица "потребитель", ссылается на действующее лицо), менеджер (таблица "менеджер ", ссылается на действующее лицо) и так далее. V>>Имея такую структуру, мы можем легко и однотипно обрабатывать все сущности. Например, добавить таблицу "адрес", ссылающуюся на "действующее лицо". V>>Пример не выдуманный, отлично жил в работающей системе.
_FR>ИМХО, для описанного сценария больше подойдёт агрегирование, в котором таблица с одной колонкой будет не нужна.
Чесно говоря, не понял, какое агрегирование имеется в виду. Засунуть все детали в одну колонку?
> OS>В вашем случае, чтобы получить 3ю нормальную форму придется делать так. > > А тот вариант, что уже есть в каком месте нарушает 3НФ? Вариант такой: > >
> CREATE TABLE NotesList (
> NoteListId int PRIMARY KEY,
> )
>
> CREATE TABLE Notes (
> NoteId int PRIMARY KEY,
> NoteListId int REFERENCES NotesList (NoteListId),
> Note text,
> )
>
> CREATE TABLE Addresses (
> AddressID int PRIMARY KEY,
> Street text,
> City text,
> AddressNoteListId int REFERENCES NotesList (NoteListId),
> StreetNoteListId int REFERENCES NotesList (NoteListId),
> CityId int REFERENCES NotesList (NoteListId),
> )
>
Выглядит не плохо... Особенно если тащить более-менее простыми запросами
в объектную модель, а там уже осмысленные вещи делать.
-- запрос списка адресов и кол-ва определенных заметок
-- для вашего вариантаSELECT A.AddressID, count(N.NoteID)
FROM Addresses A
INNER JOIN Notes N
ON N.NoteListID = A.AddressNoteListID
GROUP BY A.AddressID
-- для моего вариантаSELECT A.AddressID, count(NA.NoteID)
FROM Adresses A
INNER JOIN AddressNotes NA
ON NA.AddressID = A.AddressID
GROUP BY A.AddressID
Различия только в том, что условие N.NoteListID = A.AddressNoteListID
напрямую не подпадает под FOREIGN KEY, тогда как NA.AddressID =
A.AddressID — явно по FOREIGH KEY.
Не думаю, что для современных СУБД это представляет сложность... Хотя...
как знать.
У меня тут еще такая идея родилась. Notes не имеют к Address прямого
отношения. Это такой инструмент для работы с адресами в определенно
софте (вашем софте). Никакие операции связанные с адресами не должны
учитывать нотисы. Может быть функционально разделить эти понятия? Ввести
систему управления нотисами — она окажется простой дальше некуда.
CREATE TABLE Note (
NoteID integer PRIMARY KEY,
Note text NOT NULL,
-- дата добавления, автор, коментарий всякое такое.
Target varchar NOT NULL,
-- ex. target. 'mssql:mydb.ru:Database1:Addresses:AddressID:447'
-- или
TargetHost varchar NOT NULL,
TargetDB varchar NOT NULL,
TargetTable varchar ....
);
Эта система каким-то образом будет ссылаться на сущьности (я предлагаю
использовать какой-нибудь URL), а тот софт который будет работать с
адресами будет использовать и систему работы с адресами и систему работы
с нотисами.
Здравствуйте, _FRED_, Вы писали:
D>>А чем тут поможет еще одна таблица с ID заметок? Может сразу ссылаться на записи в таблице заметок?
И все-таки, чем тут поможет еще одна таблица с ID заметок? Может сразу ссылаться на записи в таблице заметок? Этого момента я не понял.
D>>Если количество заметок динамично для каждой сущности, то проще сделать через дополнительную таблицу для связи многие-ко-многим: EntitiesNotes (EntityId, EntityType, NoteId), где EntityType задается через where в селекте. Или чтобы отношения между таблицами не перекладывать на программистов, сделать по одному полю на каждый тип объектов: EntitiesNotes (ProductId, EmployeeId, ..., NoteId). Но тут неудобство в создании первичного ключа — надо вводить суррогатные NULL, плюс пересоздавать ключ при введении дополнительной сущности.
_FR>Вот как раз "безымянных" "EntityId, EntityType" избежать и пытаюсь. А так же созданием на каждую таблицу отдельного поля — сиквелу будет казаться, что от нотесов до какой-либо таблицы ведёт более одного пути (например, если между ProductId и EmployeeId есть связь).
Если надо именнованности, то создай еще одну таблицу EntityTypes (Type, TypeName).
Насчет казаться опять не понял. Есть связь между продуктами и служащими. Если они будут фигурировать в одном запросе, то заметки будут джойниться по вполне определенным полям определенных таблиц. Или речь про апдейт и добавление записей в эту промежуточную таблицу? И в этом случае не совсем понимаю, в чем проблема, кроме суррогатных NULL'ов. Каждое поле ссылается на одну конкретную таблицу и все. Какие там между ними связи — это разве важно?
Здравствуйте, vmpire, Вы писали:
_FR>>ИМХО, для описанного сценария больше подойдёт агрегирование, в котором таблица с одной колонкой будет не нужна. V>Чесно говоря, не понял, какое агрегирование имеется в виду. Засунуть все детали в одну колонку?
Здравствуйте, Donz, Вы писали:
D>>>А чем тут поможет еще одна таблица с ID заметок? Может сразу ссылаться на записи в таблице заметок?
D>И все-таки, чем тут поможет еще одна таблица с ID заметок? Может сразу ссылаться на записи в таблице заметок? Этого момента я не понял.
Я что-то из цитаты вопроса не уловил Можешь из меня процитировать то, что не понятно было?
_FR>>Вот как раз "безымянных" "EntityId, EntityType" избежать и пытаюсь. А так же созданием на каждую таблицу отдельного поля — сиквелу будет казаться, что от нотесов до какой-либо таблицы ведёт более одного пути (например, если между ProductId и EmployeeId есть связь).
D>Если надо именнованности, то создай еще одну таблицу EntityTypes (Type, TypeName).
Это не поможет — я хочу, что целостность заметок поддерживалась самим сервером. В твоём варианте, если я правильно его понимаю, придётся следить за этим самостоятельно.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>Интересно было бы узнать, какие проблемы могут быть из-за того, что у меня, по-сути, связь от родительской таблицы к детям, а не наоборот.
Первое пришедшее в голову — большинство ормапперов будет спотыкаться на удалении — если не обернуть всё это непотребство в хранимые процедуры (или view). Нормальный саппорт любого концептуального извращения никогда дешёвым не бывает.
Здравствуйте, _FRED_, Вы писали:
_FR>>>ИМХО, для описанного сценария больше подойдёт агрегирование, в котором таблица с одной колонкой будет не нужна. V>>Чесно говоря, не понял, какое агрегирование имеется в виду. Засунуть все детали в одну колонку? _FR>Нет, агрегирование в другом смысле. _FR>Тогда будет сразу видно, что если в таблице "действующее лицо системы" нет ни одного поля, то такая таблица попросту не нужна.
То есть, просто сделать не связанные таблицы? Я всё-таки пока не понимаю, в чём разница между этими двумя вариантами с точки зрения базы данных.
Здравствуйте, Sinix, Вы писали:
_FR>>Интересно было бы узнать, какие проблемы могут быть из-за того, что у меня, по-сути, связь от родительской таблицы к детям, а не наоборот.
S>Первое пришедшее в голову — большинство ормапперов будет спотыкаться на удалении — если не обернуть всё это непотребство в хранимые процедуры (или view). Нормальный саппорт любого концептуального извращения никогда дешёвым не бывает.
А какие будут сложности и с кем?
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, vmpire, Вы писали:
_FR>>>>ИМХО, для описанного сценария больше подойдёт агрегирование, в котором таблица с одной колонкой будет не нужна. V>>>Чесно говоря, не понял, какое агрегирование имеется в виду. Засунуть все детали в одну колонку? _FR>>Нет, агрегирование в другом смысле. _FR>>Тогда будет сразу видно, что если в таблице "действующее лицо системы" нет ни одного поля, то такая таблица попросту не нужна. V>То есть, просто сделать не связанные таблицы? Я всё-таки пока не понимаю, в чём разница между этими двумя вариантами с точки зрения базы данных.
Нет, связь будет. А разница в том, что иметь "пустую базу" может показаться кому-то оправданным, но пустой список аттрибутов — нет.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>А какие будут сложности и с кем?
Так откуда я знаю, что у вас будет использоваться и как?
Например сценарий "переместить заметку в другой список; удалить сущность и оставшиеся заметки" без допиливания напильником не прожуёт никто. Это если у вас удаление заметок оформлено триггером — чтоб не болталось дохлых. А если не триггером — мы снова вернулись к проблеме ручного управления ссылками.
Здравствуйте, Sinix, Вы писали:
_FR>>А какие будут сложности и с кем? S>Так откуда я знаю, что у вас будет использоваться и как?
S>Например сценарий "переместить заметку в другой список; удалить сущность и оставшиеся заметки" без допиливания напильником не прожуёт никто.
Такой задачи перед моими заметками, естественно, никто не ставит. Да и сомвеваюсь, что перед заметками вообще кто-нибудь ставит подобные задачи.
S>Это если у вас удаление заметок оформлено триггером — чтоб не болталось дохлых. А если не триггером — мы снова вернулись к проблеме ручного управления ссылками.
Ничего в БД кроме, собственно, таблиц не будет. Обычный UnitOfWork, в рамках которого даже задача "переместить заметку в другой список; удалить сущность и оставшиеся заметки" (если бы понадобилась) не встанет — если нужно, делается в две транзакции никому не мешая.
Help will always be given at Hogwarts to those who ask for it.
— я вот тут не мог понять, как поможет таблица Attributes. Теперь после еще одного просмотра вроде дошло
_FR>Это не поможет — я хочу, что целостность заметок поддерживалась самим сервером. В твоём варианте, если я правильно его понимаю, придётся следить за этим самостоятельно.
Если взять второй вариант, где на каждую новую сущность заводится еще одно поле, то целостность будет гарантироваться на уровне БД, но с суррогатными ключами.
Но после вкуривания задачи у меня появился еще один вариант. Насколько я понял из вышеуказанного поста, количество групп атрибутов заранее определена для каждой сущности. Если это так, и заводить по одному полю на каждую группу в данном проекте нормально, то более правильный вариант таков:
То есть логичнее содержать в группе атрибутов информацию о том, какие атрибуты в нее входят. При этом управление группами и их содержимым будет намного проще, чем если в каждом атрибуте содержать информацию о том, в какие группы он входит.
Если все-таки хочется содержать информацию о группе атрибута в нем самом, то выходит, что он может быть только в одной группе. А раз так, то зачем нам дублирующая таблица Attributes? Мы ведь можем напрямую связать сущности TableX сразу с атрибутами по идентификатору их группы. То есть будет такой вариант:
Здравствуйте, denger, Вы писали:
_FR>>Да ёлки-палки, какие могут быть варианты-то? Приведи ради интереса пару других, отличных _FR>>Например, есть таблица Заметки { NoteId, Note }, есть таблицы Товары, Служащие, Контракты, Адреса, … всё что угодно. Каждый Товар, Служащий, Контракт или Адрес может иметь несколько Заметок. Всё. Как?
D>Notes:
D> int content_type
D> varchar object_pk
D> text note_text
D> user, date, title, etc
D>content_type — идентификатор таблицы, на которую ссылается заметка. D>Как кодировать content_type и object_pk — дело ваше.
Вы, наверное, не прочитали полностью задачи — никаких неявных связей иметь не хочется. Зачем использовать колдунство, если можно без него? К тому же задача у меня не иметь возможность добавлять заметки ко всему угодно, а уметь возможность добавлять заметки к большому количеству таблиц\полей ("большому" есть больше одного). В предложенном вами сценарии (раз в пятый, наверное, в этом топике) не страивает то, что за ссылочной целостностью необходимо следить самостоятельно. Это не подходит.
D>Так сделано в комментариях джанго — вполне рабочая и достаточно универсальная модель. D>http://code.djangoproject.com/browser/django/trunk/django/contrib/comments/models.py
Да хоть в Northwind-е
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, Donz, Вы писали:
_FR>>Я что-то из цитаты вопроса не уловил Можешь из меня процитировать то, что не понятно было?
D>http://www.rsdn.ru/forum/db/3791291.1.aspx
— я вот тут не мог понять, как поможет таблица Attributes. Теперь после еще одного просмотра вроде дошло
_FR>>Это не поможет — я хочу, что целостность заметок поддерживалась самим сервером. В твоём варианте, если я правильно его понимаю, придётся следить за этим самостоятельно. D>Если взять второй вариант, где на каждую новую сущность заводится еще одно поле, то целостность будет гарантироваться на уровне БД, но с суррогатными ключами.
Криво будет гарантирована: сиквел будет думать, что существуют циклы в отношениях (например, Table1 ссылается на Table2).
D>Но после вкуривания задачи у меня появился еще один вариант. Насколько я понял из вышеуказанного поста, количество групп атрибутов заранее определена для каждой сущности. Если это так, и заводить по одному полю на каждую группу в данном проекте нормально, то более правильный вариант таков:
Тут что-то не клеится: поменять местами порядок объявления AttributeLists и Attribute я ещё в уме могу, но вот что значит ссылка на "Attributes" Это ссылка на что из первых двух?
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>>>Это не поможет — я хочу, что целостность заметок поддерживалась самим сервером. В твоём варианте, если я правильно его понимаю, придётся следить за этим самостоятельно. D>>Если взять второй вариант, где на каждую новую сущность заводится еще одно поле, то целостность будет гарантироваться на уровне БД, но с суррогатными ключами. _FR>Криво будет гарантирована: сиквел будет думать, что существуют циклы в отношениях (например, Table1 ссылается на Table2).
Что подразумевается под "будет думать"? Он же не строит при запросах полный граф всех связей, или я чего-то не догоняю? При селекте надо будет проверить одну связь. При инсерте столько связей, сколько типов сущностей.
D>>Но после вкуривания задачи у меня появился еще один вариант. Насколько я понял из вышеуказанного поста, количество групп атрибутов заранее определена для каждой сущности. Если это так, и заводить по одному полю на каждую группу в данном проекте нормально, то более правильный вариант таков:
_FR>Тут что-то не клеится: поменять местами порядок объявления AttributeLists и Attribute я ещё в уме могу, но вот что значит ссылка на "Attributes" Это ссылка на что из первых двух?
На AttributeLists. Забыл изменить название в связях.
Здравствуйте, _FRED_, Вы писали:
_FR>Ничего в БД кроме, собственно, таблиц не будет.
О, ну если приложение уже имеет прямой доступ к таблицам, можно вообще не заморачиваться и делать как удобно.
_FR>Обычный UnitOfWork, в рамках которого даже задача "переместить заметку в другой список; удалить сущность и оставшиеся заметки" (если бы понадобилась) не встанет — если нужно, делается в две транзакции никому не мешая.
Не догоняю как бизнес-транзакцию можно разбить на части, не прикручивая DTS на ровном месте.
On 05/04/2010 06:22 PM, _FRED_ wrote: > OS>Может быть функционально разделить эти понятия? > > Неявных связей между таблицами и заметками я как раз пытаюсь избежать.
Неявных не будет. Одна система — Адреса — полностью независима (и ничего
не знает про заметки), а вторая система — Заметки — имеет
документированный способ адресации сущностей из других систем, но от
самих сущностей эта вторая система тоже не зависит.
Есть сущность (в какой-то системе), есть ее "адрес" (для системы
заметок), есть набор заметок для этой сущности и собственно система для
работы с этими заметками.
Пользовательский интерфейс будт работать с двумя системами одновременно.
Address a = addressService.getAddress(?);
NotesList notesList = notesService.getNotesList(createNotesUrl(a));
lblAddress.setText(a.toString());
lblNotesCount.setText(String.valueOf(notesList.getSize()));
public String createNotesUrl(Address a){}
public String createNotesUrl(Address a, String fieldName){}
Здравствуйте, Donz, Вы писали:
D>Здравствуйте, _FRED_, Вы писали:
_FR>>>>Это не поможет — я хочу, что целостность заметок поддерживалась самим сервером. В твоём варианте, если я правильно его понимаю, придётся следить за этим самостоятельно. D>>>Если взять второй вариант, где на каждую новую сущность заводится еще одно поле, то целостность будет гарантироваться на уровне БД, но с суррогатными ключами. _FR>>Криво будет гарантирована: сиквел будет думать, что существуют циклы в отношениях (например, Table1 ссылается на Table2).
D>Что подразумевается под "будет думать"? Он же не строит при запросах полный граф всех связей, или я чего-то не догоняю? При селекте надо будет проверить одну связь. При инсерте столько связей, сколько типов сущностей.
CREATE TABLE Table1 (
Id int PRIMARY KEY,
)
CREATE TABLE Table2 (
Id int PRIMARY KEY,
Table1Id int REFERENCES Table1 (Id),
)
CREATE TABLE Attributes (
Id int PRIMARY KEY,
Table1Id int REFERENCES Table1 (Id),
Table2Id int REFERENCES Table2 (Id),
)
INSERT INTO Table1 VALUES (1)
INSERT INTO Table2 VALUES (1, 1)
INSERT INTO Attributes VALUES (1, 1, NULL)
INSERT INTO Attributes VALUES (2, NULL, 1)
DELETE FROM Table2 WHERE Id = 1
Delete обломится:
The DELETE statement conflicted with the REFERENCE constraint "FK__Attribute__Table__2F10007B". The conflict occurred in database "ZZZ", table "dbo.Attributes", column 'Table2Id'.
D>>>Но после вкуривания задачи у меня появился еще один вариант. Насколько я понял из вышеуказанного поста, количество групп атрибутов заранее определена для каждой сущности. Если это так, и заводить по одному полю на каждую группу в данном проекте нормально, то более правильный вариант таков: _FR>>Тут что-то не клеится: поменять местами порядок объявления AttributeLists и Attribute я ещё в уме могу, но вот что значит ссылка на "Attributes" Это ссылка на что из первых двух? D>На AttributeLists. Забыл изменить название в связях.
Не подходит — нигде не сказано, что Attribute->Name может переиспользоваться. Они вообще уникальны. Например, вместо Name — текст заметки типа text. Тут получается просто просто связь многие-ко-многим между Table1…2 и Attribute. Этого не надо. Нудно многие-к-одному между Attribute и Table1…2.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, Sinix, Вы писали:
_FR>>Обычный UnitOfWork, в рамках которого даже задача "переместить заметку в другой список; удалить сущность и оставшиеся заметки" (если бы понадобилась) не встанет — если нужно, делается в две транзакции никому не мешая. S>Не догоняю как бизнес-транзакцию можно разбить на части, не прикручивая DTS на ровном месте.
"переместить заметку в другой список" — это изменение двух сущностей (откуда перемещают и куда перемещают). "удалить сущность и оставшиеся заметки" — это изменение первой сущности. Необходимость выполнения обоих операций в одной бизнес-транзакции вызывает сомнения.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, Other Sam, Вы писали:
OS>On 05/04/2010 06:22 PM, _FRED_ wrote: >> OS>Может быть функционально разделить эти понятия? >> >> Неявных связей между таблицами и заметками я как раз пытаюсь избежать.
OS>Неявных не будет.
Неявная — эта та, целостность которой не может быть обеспечена средствами сервера. Тащить на сервер логику распознования юрл в то время, когда можно обойтись внешними ключами весьма странно. А иных требований (кроме явных связей) я в своей задаче не выдвигал.
Help will always be given at Hogwarts to those who ask for it.
_FR>CREATE TABLE Attributes (
_FR> Id int PRIMARY KEY,
_FR> Table1Id int REFERENCES Table1 (Id),
_FR> Table2Id int REFERENCES Table2 (Id),
_FR>)
_FR>
_FR>Delete обломится:
Согласен.
_FR>Не подходит — нигде не сказано, что Attribute->Name может переиспользоваться. Они вообще уникальны. Например, вместо Name — текст заметки типа text. Тут получается просто просто связь многие-ко-многим между Table1…2 и Attribute. Этого не надо. Нудно многие-к-одному между Attribute и Table1…2.
Как уже писал, если связь многие-к-одному, то зачем вообще дополнительная таблица, содержащая только ID?
Чем не устраивает этот вариант:
Здравствуйте, Donz, Вы писали:
D>Как уже писал, если связь многие-к-одному, то зачем вообще дополнительная таблица, содержащая только ID? D>Чем не устраивает этот вариант:
On 05/04/2010 08:41 PM, _FRED_ wrote: > Неявная — эта та, целостность которой не может быть обеспечена > средствами сервера. Тащить на сервер логику распознования юрл в то > время, когда можно обойтись внешними ключами весьма странно. А иных > требований (кроме явных связей) я в своей задаче не выдвигал.
В проектировании информационных систем есть понятия свзяности и
зацепления. GRASP паттерны проектирования Low Coupling и High Cohesion.
(на всякий случай http://ru.wikipedia.org/wiki/GRASP ).
Вы пытаетесь возложить обязанности по обеспечению целостности данных на
RDBMS. Отлично, делайте таблички связей многие-ко-многим для каждой
сущности у которой должны быть наборы Notes. (Я уже ранее приводил
пример SQL кода).
Я же предлагаю разделить функциональность по двум системам, что позволит
заметно упростить каждую из систем, и в обоих системах целостность
данных будет поддерживаться средствами базы данных, без дополнительных
усилий.
Однако тащить на сервер баз данных логику распознавания URL нет смысла.
Когда вы разделите систему на две части вам не придется в SQL
распознавать URL.
On 05/04/2010 08:38 PM, _FRED_ wrote: > "переместить заметку в другой список" — это изменение двух сущностей > (откуда перемещают и куда перемещают). "удалить сущность и оставшиеся > заметки" — это изменение первой сущности. Необходимость выполнения обоих > операций в одной бизнес-транзакции вызывает сомнения.
Разделяйте на две системы! Что означает "переместить заметку в другой
список" с точки зрения управления адресами? Это что, уточнение адреса,
добавление нового, удаление устаревшего адреса? Нет! Это вообще к
адресам никакого отношения не имеет. Это относится только к заметкам.
Так с какого перепугу вы называете это "изменение двух сущностей" (имея
ввиду изменение двух адресов)?
> Как при создании новой записи в Table1 получать новый ListId? через > SELECT MAX + 1? Чем это лучше лишней таблицы у меня?
АГА! Генерация уникальных ID Смотрите первый пост в ответах в этом
обсуждении (мой пост). > С точки зрения нормального дизайна, я думаю, что не существует. > Скорее всего требовалось обеспечить генерацию уникальных > идентификаторов. В постгриз для этого есть sequense. В других базах > тоже бывает что-то такое.
Здравствуйте, _FRED_, Вы писали:
D>>Как уже писал, если связь многие-к-одному, то зачем вообще дополнительная таблица, содержащая только ID? D>>Чем не устраивает этот вариант: _FR>
_FR>Как при создании новой записи в Table1 получать новый ListId? через SELECT MAX + 1? Чем это лучше лишней таблицы у меня?
А зачем при создании записи получать новый ListId? Насколько я понимаю, надо получить уже существующий, который соответствует данной сущности. Или не так?
Если имелось в виду получение нового ListId при добавлении новой сущности, то это лучше тем, что select max + 1 надо выполнить один раз при добавлении этой сущности (а это, наверное, не так часто случается). А дополнительная таблица с продублированными данными и дополнительной связью (и вся эта структура не совсем очевидна) будет всегда. Она как минимум будет мешать разработчику читать запросы
Если дополнительная таблица все же так необходима, то связь "группа атрибутов-атрибут" лучше перенести в нее. Связь многие-ко-многим очень просто превращается в связь многие-к-одному путем объявления поля AtributId UNIQUE:
Здравствуйте, Other Sam, Вы писали:
>> Как при создании новой записи в Table1 получать новый ListId? через >> SELECT MAX + 1? Чем это лучше лишней таблицы у меня?
OS>АГА! Генерация уникальных ID Смотрите первый пост в ответах в этом OS>обсуждении (мой пост). >> С точки зрения нормального дизайна, я думаю, что не существует. >> Скорее всего требовалось обеспечить генерацию уникальных >> идентификаторов. В постгриз для этого есть sequense. В других базах >> тоже бывает что-то такое.
Извиняюсь, но "слышу звон, но не знаю, где он" — какое отношение мои слова о "SELECT MAX + 1" имеют к "Смотрите первый пост в ответах"?
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, Donz, Вы писали:
D>>>Как уже писал, если связь многие-к-одному, то зачем вообще дополнительная таблица, содержащая только ID? D>>>Чем не устраивает этот вариант:
_FR>>Как при создании новой записи в Table1 получать новый ListId? через SELECT MAX + 1? Чем это лучше лишней таблицы у меня?
D>А зачем при создании записи получать новый ListId? Насколько я понимаю, надо получить уже существующий, который соответствует данной сущности. Или не так?
Покажи, как будет происходить добавление новой строки в Table1.
D>Если имелось в виду получение нового ListId при добавлении новой сущности, то это лучше тем, что select max + 1 надо выполнить один раз при добавлении этой сущности (а это, наверное, не так часто случается). А дополнительная таблица с продублированными данными и дополнительной связью (и вся эта структура не совсем очевидна) будет всегда. Она как минимум будет мешать разработчику читать запросы
Не понимаю, о какой таблице "с продублированными данными и дополнительной связью" речь.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>Покажи, как будет происходить добавление новой строки в Table1.
Возьму вот эту цитату:
Например, есть таблица Заметки { NoteId, Note }, есть таблицы Товары, Служащие, Контракты, Адреса, … всё что угодно. Каждый Товар, Служащий, Контракт или Адрес может иметь несколько Заметок. Всё. Как?
Тогда свои таблицы я бы создал такими:
create table Attrbutes
(
id int4 primary key auto_increment,
name varchar
);
create table Table1
(
id int4 primary key auto_increment,
name varchar,
attr int4 null
);
alter table Table1 add foreign key attr_attr_id (attr) references Attributes(id);
Добавление записей выглядит вот так:
insert into Attributes(name) values ('new attr for new Table1 record');
select max(id) from Attributes;
//Тут куда-нибудь записали этот id
insert into Table1(name, attr) values ('new record', attr_id);
Как-то так.
Можешь в свою очередь написать на скуле свой вариант с добавления записей?
On 05/04/2010 10:37 PM, _FRED_ wrote: > Извиняюсь, но "слышу звон, но не знаю, где он" — какое отношение мои > слова о "SELECT MAX + 1" имеют к "Смотрите первый пост в ответах"?
SELECT MAX + 1 — это ничто иное как генерация уникальных ID. Поскольку
при нескольких одновременных транзакциях MAX + 1 гораздо более
проблемный чем вставка новой записи в таблицу с автоинкрементируемым
полем, то некоторые "проектировщики" решают пользоваться отдельной
таблицей с одним единственным автоинкрементируемым полем.