[SQL] тупняк (теория построения БД)
при этом не должно быть так, что в В есть такие записи, которые через сВ ссылаются на такую запись в сА, которая отлична от сА, на которую этот элемент ссылается через А.Или я торможу, или это значит, что в cB и A есть дублирующиеся данные? Чего по принципам НФ быть не должно...
Поэтому предлагаю залинковать В напрямую на сА, а А и сВ залинковать на В.
Будет косяк, если существуют строчки в А и сВ, у которых нету ссылающихся на них строчек из В. Тогда можно, например, подумать о создании заглушечных строчек в В для таких случаев. Скорее всего, это будет даже осмысленно в терминах моделируемой системы.
сА - услуга, сВ - вариант предоставления услуги А - документ по контролю за услугой (на одну услугу может быть несколько док-ов В - строка документа (документ может охватывать не все варианты)надеюсь это не подпадает под нарушение НДА )
у меня получается только если делать составной PK, часть из которого ссылка на "родителя"
у меня получается только если делать составной PK, часть из которого ссылка на "родителя"а не пля, не получается - на одно поле два констрейна же не повесишь
В смысле почему строчки документа завязаны на вариант предоставления услуги? Это выглядит странно.
я в этой предметной области пока вообще полный ноль.
повторюсь:
все четыре таблицы помимо ссылок содержат также и данные.
связка А+В1+В2 как бы расширяет связку сА+сВ1+сВ2+сВ3, при этом на одну может быть нанизано несколько.
при этом сА и сВ одновременно являются ещё и справочниками, и много где помимо этого места используются.
руки бы конечно поотрывать за такие солюшены.
связка А+Б1+Б2 как бы расширяет связку сА+сБ1+сБ2+сБ3, при этом на одну может быть нанизано несколько.Ты ввел какиетто новые обозначения, и я не понял твою мысль.
Поясню свой вопрос. В исходной модели получается, что разные строчки одного документа могут ссылаться на разные варианты предоставления услуги. Звучит это довольно бредово, так как строчки документа в моем понимании не есть самостоятельная сущность, и в худшем случае документ бы ссылался на вариант предоставления.
Тогда их возможно получилось бы линейно выстроить.
я имел в виду запись из таблицы А + ссылающиеся на эту запись записи из В.
аналогично сА и сВ.
В новой табличке валидировать соотв правила (у документа один услуг, у варианта один услуг).
Хз как лучше.
короче я думаю куй с ним - пускай всё остаётся как есть - не стоит оно возни.
но квадратик из верхнего поста представил себе так:
B — жилые помещения, А — почтовые отделения, сB — улицы, сА — регионы
это та же задача?
можешь в этих терминах рассказать своё решение?
если это поможет представить картину
сА - услуга, сВ - вариант предоставления услуги А - документ по контролю за услугой (на одну услугу может быть несколько док-ов В - строка документа (документ может охватывать не все варианты)
А -> сА
/\ /\
| |
Б -> сБ
ничего не понятно всё равно. Может быть и нет никакой ошибки... Ну как пример:
Пусть в cА — вид услуг, там Алиса, Катерина, Антуанетта и т.д.
В Б — запись вида "в 23:20 была оказана услуга вариантом представления сБ, на что имеются документы в А".
Задача, узнать, кто оказывал услугу.
Смотрим таблицу А, находим там, что для этой услуги есть чеки об оказании, на 200 евро, со ссылкой на сА, на Алису.
Смотрим таблицу сБ, там есть услуга "доставка шампанского на дом", со ссылкой на сА, но уже на Катерину.
Вопрос, так кто же работал, Алиса, или Катерина?
Почему сбой мог произойти — понятно, скажем, когда заказывалась услуга, планировалось, что её будет оказывать Катерина, но по факту получилось, что оказывала Алиса. Вполне себе нормальная ситуация.
В данном случае даже нельзя сказать, что грубая ошибка в проектировании есть. То есть нет проблемы в синхронизации данных. Просто цепочка Б --> сБ --> сА некорректна, она не отвечает на вопрос "кто работал", она отвечает на вопрос "кто должен был работать".
Вообще, IHMO, надо в структуре базы детально разбираться, чтобы понять, это база криво спроектирована, либо же она просто криво задокументирована.
Рвешь все связи, делаешь табличку для тернарной связи между регион-отделение-улица. На эту табличку линкуешь дома.
Соответственно теперь, чтобы убедиться в корректности связей, достаточно одной новой таблицы. Проверяем что у всех строчек с заданным отделением одинаковый регион, и, аналогично, у всех улиц. Это, конечно, на дефолтных констрейнтах не.
Вообще, вся загвоздка в том, как реляционно красиво представить такую структуру:
Регион, у которого много отделений, много улиц. Множества отделений и улиц между разными регионами не пересекаются. Дом может выбирать улицы и отделения только из одно и того же региона.
В принципе, можно оставить то, как есть сейчас (регион один-ко-многим отделениям, регион один-ко-многим улицам порвать связь между домами и всем остальным. Создать вьюху из примерно такого селекта:
select
stable_unique_id(Region.id, Post.id, Street.id Region.id, Post.id, Street.id
from
Region
join Post on Post.RegionId = Region.id
join Street on Street.ReionId = Region.id
и линковать дома на эту вьху. Тогда никакой валидации вьюхи делать не надо будет.
я нихрена не понял как там с документами и услугами
ничего не понятно всё равно.придумал такой вот пример:
сА - Банк (ИД(PK название, БИК, КПП и т.д.)
банк может обслуживать организации:
А - Организация (ИД(PK название, банк_ИД(FK год_основания, уставной_капитал и т.д.)
в банке есть банковские ячейки:
сВ - Ячейка (ИД(PK банк_ИД(FK объём_ячейки, на_какой_срок_арендована и т.д.)
каждый сотрудник организации может работать только в одной организации и иметь ячейку в банке, который обслуживает организацию (и только в нём или же не иметь.
В - Сотрудник (ИД(РК организация_ИД(FK ячейка_ИД(FK имя, фамилия, зарплата, рост и т.д.)
stable_unique_idЭто что за зверь? не гуглится что-то.
CREATE OR REPLACE VIEW MyView (О_ИД, Я_ИД)
AS
SELECT o.ИД AS , я.ИД AS Я_ИД
FROM Банк б
JOIN
Организация o
ON o.банк_ИД = б.ИД
JOIN
Ячейка я
ON я.банк_ИД = б.ИД
ALTER TABLE Сотрудник ADD
CONSTRAINT fk_cотрудник_яч_орг FOREIGN KEY (организация_ИД, ячейка_ИД) REFERENCES MyView (О_ИД, Я_ИД)
Короче, это просто композитный ключ, на который можно слинковаться из домов/строчек. В примере выше ты без этого обошелся =)
Если твоя БД это проглотит, и коллеги тебя не побьют, то в общем да =)
ещё не видел таких БД, которые не умели бы ссылаться сразу двумя полями.
от так всегда
но тут случилось ОПАНЬКИ: You can't reference a view in a foreign key.
Есть у кого идеи?
Может гугл по вариантам представления тернарных связей в рбд что-нибудь еще предложит.
1) как правильно с точки зрения НФ и прочих постулатов теории БД делаются такие вещи?в описаной тобой схеме с постулатами противоречий нет.
2) как минимально затронув эту конструкцию переделать так, чтобы больше таких флуктуаций не возникало?
В принципе это нафиг не нужно, по любому надо чинить приложение, которое пишет такие кривые данные. Но если все же хочется извращений — контроля со стороны базы, то можно добавить поле В.cAId. Повесить составные уникальные индексы на таблицах A и cB, и сделать в таблице B два FK на эти уникальные индексы (например, MS SQL Server такое позволяет).
добавить поле В.cAId
если надо, то можно привести обоснование из предметной области почему это поле не противоречит нормальным формам.
Флуктуации возникают скорее всего при импорте, который идет в обход сервера приложений (из 1С например так что следить за этим программно нет возможности. В идеале конечно бы триггер перед вставкой повесить - он решил бы все проблемы. Но они, к сожалению, запрещены по идейным причинам (хотя лишние view тоже крайне не приветствуются).
ALTER TABLE В
ADD cAId numeric(15)
ALTER TABLE В
ADD CONSTRAINT fk_b_A FOREIGN KEY (Aid, cAId) REFERENCES A(id, cAid)
ALTER TABLE В
ADD CONSTRAINT fk_b_сВ FOREIGN KEY (сВid, cAId) REFERENCES сВ(id, cAid)
т.е. на cAId будет два FK повешено. так можно?
UPD: и правда можно на одно поле два FK повесить.
Тогда вопрос такой: как в A и сВ создать индекс уникальный по этим полям id, cAid (чтобы было на что ссылаться FK)
Я тебя правильно понялда, правильно, FK, естественно, на таблице B (у меня была опечатка).
Тогда вопрос такой: как в A и сВ создать индекс уникальный по этим полям id, cAid (чтобы было на что ссылаться FK)ну как-нибудь так:
ALTER TABLE A ADD CONSTRAINT AIndex UNIQUE(AId, cAId)
ALTER TABLE cB ADD CONSTRAINT cBIndex UNIQUE(cBId, cAId)
Проще такое мышкой сделать, а потом скрипт посмотреть. У меня сейчас, к сожалению, нет доступа к SQL Server-у.
Вообще, вот отсюда и далее по ссылкам:
A UNIQUE constraint can be referenced by a FOREIGN KEY constraint.
http://msdn.microsoft.com/en-us/library/ms191166.aspx
только MS SQL S. у нас только раньше поддерживался, и мб в будучем отдалённом.
придумал такой вот пример:У нас это выглядит так:
сА - Банк (ИД(PK название, БИК, КПП и т.д.)
банк может обслуживать организации:
А - Организация (ИД(PK название, банк_ИД(FK год_основания, уставной_капитал и т.д.)
в банке есть банковские ячейки:
сВ - Ячейка (ИД(PK банк_ИД(FK объём_ячейки, на_какой_срок_арендована и т.д.)
каждый сотрудник организации может работать только в одной организации и иметь ячейку в банке, который обслуживает организацию (и только в нём или же не иметь.
В - Сотрудник (ИД(РК организация_ИД(FK ячейка_ИД(FK имя, фамилия, зарплата, рост и т.д.)
А (организация) Поля(A): A_ID;
/\
|
B (сотрудник) Поля(B): B_ID; cA__OID; A__OID;
/\ |
| \/
cB(ячейка) --> cA (банк) Поля(cA): cA_ID;
Поля(cB):cB_ID; B__OID; cA__OID
У вас в одной организации сотрудники могут иметь ячейки в разных банках, что опять-таки противоречит
Оставить комментарий
kill-still
таблица В ссылается на Атаблица сВ ссылается на сА
таблица А ссылается на сА
таблица В ссылается на сВ
все четыре таблицы помимо ссылок содержат также и данные.
вот так:
при этом не должно быть так, что в В есть такие записи, которые через сВ ссылаются на такую запись в сА, которая отлична от сА, на которую этот элемент ссылается через А.
собственно это косяк из-за которого я полез разбираться в это г, и его надо поправить.
у меня 2 вопроса:
1) как правильно с точки зрения НФ и прочих постулатов теории БД делаются такие вещи?
2) как минимально затронув эту конструкцию переделать так, чтобы больше таких флуктуаций не возникало?