Если вы разрабатываете с учетом текущих классов, я бы предпочел ваш вариант 3 в качестве предпочтительного варианта по причинам, указанным выше.
Ваш запрос о:
However, I'm not sure how to create the relationship between the Items table and the
Widgets and Doohickies tables. I don't want to end up with row in either table
referencing the same ItemID in the Items table.
Предложение Билла выше, безусловно, хороший вариант. Что-то, о чем я не думал :-)
Однако я подумал, что это отношение, которое вы можете применить либо в самом коде приложения, либо с помощью триггера вставки.
Однако меня беспокоит попытка смоделировать само наследование на уровне БД.
Если ожидается, что число дочерних классов будет расти в течение определенного периода времени, такой тип разработки БД может стать очень сложным для обслуживания.
В дополнение к:
Items Table: ItemID (PK), Name, Size
Widgets Table: WidgetID (PK), ItemID (FK), Color
Doohicky Table: DoohickyID (PK), ItemID (FK), Smell
Какова вероятность добавления новых классов, таких как следующие?
DontDoHicky Table : DoohickyID (PK), ItemID (FK), Smell, **TASTE**
MidWidget Table : WidgetID (PK), ItemID (FK), Color , **Height**
MidDoHicky Table : WidgetID (PK), ItemID (FK), **Height**, **Smell**
Это, конечно, классическая проблема наследования ОО.
Если вы ожидаете, что приложение будет расти таким образом в течение определенного периода времени, и, возможно, вам необходимо запланировать это заранее, на уровне БД, вы можете предпочесть использовать более общий подход
Items Table: ItemID (PK), Name, Size, **ItemType**
**ItemAttributes Table : ItemID (PK), AttributeID, AttributeName, AttributeValue**
Это позволит вам легко применить ограничение 1: 1 и легко запросить все атрибуты, используя AttributeName, если они являются стандартными.
Это, вероятно, старомодный подход и не очень объектно-ориентированный, но он может быть более подходящим, исходя из будущей гибкости.