表行引用一个或另一个表

时间:2010-01-19 12:36:46

标签: sql database-design

我有一个包含某种items的表格,以及这些项目所属的两个表格(ab)。

一个项目指的是a 中的 中的一行b中的一行。一个ab可以包含多个项目。

是否有比以下更好的设计(使用Oracle 10)?

需要注意的任何陷阱?

id   a_id(fk)    b_id(fk)
 1          1        NULL
 2          1        NULL
 3       NULL           1
 4          2        NULL

4 个答案:

答案 0 :(得分:4)

在许多方面,这是一个非常好的设计:

  • 使用a_id上的外键,强制执行指向表A的链接。
  • 使用b_id上的外键强制执行到表B的链接。
  • 1:多个关系(项目与表格A之间,项目与表格B之间)均正确存储。

唯一的障碍是这个数据库结构本身不会检查项目是否只链接到A或B中的一个(而不是两者)。检查Items表上的约束将完成此任务。

伪代码示例:

CONSTRAINT a_eor_b CHECK 
  (
    NOT (a_id IS NULL AND b_id IS NULL)
    AND NOT (a_id IS NOT NULL AND b_id IS NOT NULL)
  )

答案 1 :(得分:2)

我建议添加一个检查约束,该约束强制执行至少(或可能确切地)其中一个id字段为空。

值nvl(a_id,b_id)的基于视图和/或函数的索引也可能有用。使用Oracle11,您可以使用虚拟列。

答案 2 :(得分:0)

AB是更一般类型的不相交的子类型。

我们称之为refs

CREATE TABLE refs (type CHAR(1) NOT NULL, id INT NOT NULL, PRIMARY KEY (type, id), CHECK (type IN ('A', 'B')))

CREATE TABLE a (type CHAR(1) NOT NULL, id INT NOT NULL PRIMARY KEY, FOREIGN KEY (type, id) REFERENCES refs (type, id) ON DELETE CASCADE, CHECK (type = 'A'))

CREATE TABLE b (type CHAR(1) NOT NULL, id INT NOT NULL PRIMARY KEY, FOREIGN KEY (type, id) REFERENCES refs (type, id) ON DELETE CASCADE, CHECK (type = 'B'))

CREATE TABLE items (id INT NOT NULL, type CHAR(1) NOT NULL, ref INT NOT NULL, FOREIGN KEY (type, id) REFERENCES refs)

使用此设计,您不应直接从AB删除:请从父表refs中删除。

答案 3 :(得分:0)

参考Mapping Inheritance Structures,其中提到了4种技术,

  • 将整个类层次结构映射到单个表
  • 将每个具体类映射到自己的表
  • 将每个班级映射到自己的表格
  • 将类映射到通用表结构

并查看专业人员的“2.6比较策略”缺点