设计SQL数据库以表示OO类层次结构

dal*_*lle 15 sql oop database-design

我正在将类层次结构转换为存储在SQL数据库中.

原始代码:

abstract class Note
{
   int id;
   string message;
};

class TimeNote : public Note
{
   time_t time;
};

class TimeRangeNote : public Note
{
   time_t begin;
   time_t end;
};

class EventNote : public Note
{
   int event_id;
};

// More classes deriving from Note excluded.
Run Code Online (Sandbox Code Playgroud)

目前我有几个想法如何将其存储在数据库中.

A.将所有笔记存储在一个宽表中

该表将包含派生自所有类所需的所有信息Note.

CREATE TABLE t_note(
   id INTEGER PRIMARY KEY,
   message TEXT,
   time DATETIME,
   begin DATETIME,
   end DATETIME,
   event_id INTEGER
);
Run Code Online (Sandbox Code Playgroud)

未来的类派生自Note需要向此表添加新列.

B.将每个类映射到表

CREATE TABLE t_note(
   id INTEGER PRIMARY KEY,
   message TEXT
);

CREATE TABLE t_timenote(
   note_id INTEGER PRIMARY KEY REFERENCES t_note(id),
   time DATETIME
);

CREATE TABLE t_timerangenote(
   note_id INTEGER PRIMARY KEY REFERENCES t_note(id),
   begin DATETIME,
   end DATETIME
);

CREATE TABLE t_eventnote(
   note_id INTEGER PRIMARY KEY REFERENCES t_note(id),
   event_id INTEGER
);
Run Code Online (Sandbox Code Playgroud)

未来的类派生自Note需要创建一个新表.

C.使用数据库规范化和VARIANT/SQL_VARIANT

CREATE TABLE t_note(
   id INTEGER PRIMARY KEY,
   message TEXT
);

CREATE TABLE t_notedata(
   note_id INTEGER REFERENCES t_note(id),
   variable_id TEXT, -- or "variable_id INTEGER REFERENCES t_variable(id)".
                     -- where t_variable has information of each variable.
   value VARIANT
);
Run Code Online (Sandbox Code Playgroud)

未来的类派生Note需要添加新的variable_id.

D.将每个具体类映射到一个表 (根据当前答案新添加)

CREATE TABLE t_timenote(
   id INTEGER PRIMARY KEY,
   message TEXT,
   time DATETIME
);

CREATE TABLE t_timerangenote(
   id INTEGER PRIMARY KEY,
   message TEXT,
   begin DATETIME,
   end DATETIME
);

CREATE TABLE t_eventnote(
   id INTEGER PRIMARY KEY,
   message TEXT,
   event_id INTEGER
);
Run Code Online (Sandbox Code Playgroud)

未来的类派生自Note需要创建一个新表.


SQL中最合乎逻辑的表示是什么?
还有更好的选择吗?

p.m*_*ino 8

一般来说,我更喜欢obtion"B"(即一个表用于基类,一个表用于每个"具体"子类).

当然,这有一些缺点:首先,每当你必须阅读子类的完整实例时,你必须加入至少2个表.此外,任何必须操作任何类型的笔记的人都会不断访问"基础"表.

但这通常是可以接受的,除非您有极端情况(数十亿行,需要非常快的响应时间等).

还有第三种可能的选择:将每个子类映射到不同的表.这有助于对对象进行分区,但通常会在开发工作中花费更多.

对于一个完整的讨论.

(关于你的"C"解决方案,使用VARIANT:我无法对优点/缺点发表评论,因为它看起来像一个专有的解决方案 - 它是什么?Transact-SQL?我并不熟悉它).