TL; DR
По вопросу:
child
PARENT_ID // <-- Should this column be here?
Да , и если ограничение по внешнему ключу добавлено из child.PARENT_ID
ссылаясь на родительский столбец parent.PARENT_ID
, будет обеспечена целостность отношения родитель-потомок.
Должна ли существовать таблица parent_has_children
?
Нет, ссылка или объединенная таблица, как эта, используется для моделирования many-many
отношения.Соотношение «многие-многие» между таблицами P
и C
подразумевает, что одна и та же строка C
может одновременно ассоциировать множество P
строк, и наоборот.Это явно не родительско-дочерние отношения.
Моделирование отношения 1-ко-многим
Если отношение является одним из родителей для многих детей (то есть одного и того же ребенка)может принадлежать только одному родительскому элементу), тогда стандартный подход к моделированию заключается в обращении к родительской таблице из дочерней таблицы через (один из) ключевых столбцов родительского элемента, обычно это первичный ключ родительского элемента (PK).В то же время целесообразно использовать ограничение внешнего ключа (FK) для ссылочного столбца (child.PARENT_ID
), чтобы побудить RDMBS обеспечить ссылочную целостность во всех отношениях:
parent
-------------
PARENT_ID PRIMARY KEY, // PK for the parent table
OTHER_COL
...
child
-------------
CHILD_ID PRIMARY KEY, // PK for the Child Table
PARENT_ID // <-- Should this column be here? = Yes
CONSTRAINT FK_ChildParent FOREIGN KEY(PARENT_ID) REFERENCES parent(PARENT_ID)
Дополнительная таблица «многие: многие» в операторе * является избыточной, так как она будет иметь ровно одну строку на child
, и вскоре станет бременем поддерживать эту таблицу in sync
с добавлением / удалением строк издругие таблицы (поскольку несоблюдение этой синхронизации приведет к путанице / противоречиям в целостности отношений).
Re: Как родители узнают о своих детях?
Дочерние записи для данного родителя можно найти с помощью простого запроса к дочерней таблице, отфильтрованной по столбцу внешнего ключа родителя:
SELECT ...
FROM child
WHERE PARENT_ID = myParentId;
Поскольку обычно это обычный запрос, всегда полезноубедитесь, что внешний ключ child.PARENT_ID
проиндексирован - некоторые версии РСУБД по умолчанию делают это для всех внешних ключей.
CREATE INDEX IXFoo on child(PARENT_ID);
Если у вас есть модель объекта (например, дляORM) в приложении, представляющем эти таблицы, родительский объект обычно будет иметь коллекцию, содержащую его child
экземпляров, а на дочернем объекте скалярный внешний ключ child.PARENT_ID
'column' либо удаляется полностью, либо заменяется нассылка на экземпляр родительского элемента:
class Parent
{
ParentId,
Child[] Children,
// ...
}
class Child
{
ChildId,
Parent Parent, // Optional, allows bidirectional navigation
// ...
}