Oracle 中的外键约束
我有实体关系模型 (ERD),其中实体 IndividualCategory
和 TeamCategory
与实体 Category
相关。现在我想在 Oracle DB 中创建表。我是这样开始的:
CREATE TABLE Category(
category_id INT PRIMARY KEY,
...
);
CREATE TABLE Individual_category(
category_id INT CONSTRAINT fk_cat_indivcat REFERENCES Category(category_id),
...,
CONSTRAINT pk_indivgamecat PRIMARY KEY (category_id)
);
CREATE TABLE Team_category(
category_id INT CONSTRAINT fk_cat_teamcat REFERENCES Category(category_id),
...,
CONSTRAINT pk_teamcat PRIMARY KEY (category_id)
);
外键和主键约束的组合确保对于每个Individual_category
在Category中都会有相应的记录
“超级”表(或“父”表?)。对于特定的Category
记录,只有一个IndividualCategory
记录。 Team_category
也是如此。
为了强制继承,我还需要一个约束:一个约束,确保对于 Category
中的每条记录,IndividualCategory
(X) 中都会有一个记录,或者 中会有一个记录TeamCategory
但不是两者。
我如何创建这样的约束?
编辑:这就是我所说的“ER 模型中的继承”的意思。这是来自我的数据库老师的幻灯片(他们在那里称之为“实体子类型”,但有时他们称之为继承):
I have Entity Relationship Model (ERD) where entities IndividualCategory
and TeamCategory
relate to entity Category
. Now I want to create tables in Oracle DB. I started like this:
CREATE TABLE Category(
category_id INT PRIMARY KEY,
...
);
CREATE TABLE Individual_category(
category_id INT CONSTRAINT fk_cat_indivcat REFERENCES Category(category_id),
...,
CONSTRAINT pk_indivgamecat PRIMARY KEY (category_id)
);
CREATE TABLE Team_category(
category_id INT CONSTRAINT fk_cat_teamcat REFERENCES Category(category_id),
...,
CONSTRAINT pk_teamcat PRIMARY KEY (category_id)
);
This combination of Foreign key and Primary key constraints assures that for every Individual_category
there will be corresponding record in Category
"super" table (or "parent" table ?). And there will be only one IndividualCategory
record for particular Category
record. Same for Team_category
.
To enforce inheritance I need one more constraint: A constraint that assures that for every record in Category
there will be either record in IndividualCategory
(X)OR a record in TeamCategory
but not both.
How do I create such constraint ?
EDIT: This is what I meant by 'inheritance in E-R model'. This is from my DB teacher's slides (they call it "Entity sub-type" there but they sometimes call it just inheritance):
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
使用可延迟约束来实现此目的的一种完全不同的方法是:
确保类别是 TeamCategory x 或 individualCategory:
创建可延迟完整性约束,以便可以在同一事务中插入类别和 Team/Individual_Category;否则,您无法在 TeamCategory/IndividualCategory 之前插入类别,反之亦然。第 22 条军规。
A completely different way to do this using deferrable constraints:
Make sure a
Category
is a TeamCategory xor an IndividualCategory:Create deferrable integrity constraints so that one can insert a Category and Team/Individual_Category within the same transaction; otherwise, you couldn't insert a Category before the TeamCategory/IndividualCategory, and vice-versa. A catch-22.
如何做到这一点,使用一个简化的示例:
然后您可以创建视图,例如:
您甚至可以在视图上放置一个
INSTEAD OF
触发器,以便应用程序看起来像是一张表和其他人一样。How one may do this is, using a simplified example:
You could then create views, like:
You can even put an
INSTEAD OF
trigger on the view so it would be appear to the application to be a table like any other.在数据库中实现复杂约束的另一种方法是使用物化视图 (MV)。
对于此示例,MV 可以定义如下:
因此,仅针对违反规则的类别填充 MV,但检查约束确保导致 MV 中的行的任何事务都将失败(因为 1=0 永远不会失败)真的)。
我过去曾在此处写过有关此方法的博客。
警告:虽然我对这种方法很感兴趣,但我从未在生产数据库中“愤怒地”使用过它。需要仔细进行基准测试,以确保每当数据更改时完整 MV 刷新的开销不会太高。
Another way to implement complex constraints in the database is using materialized views (MVs).
For this example an MV could be defined as follows:
So the MV is populated only for categories that break the rule, but then the check constraint ensures that any transaction that results in a row in the MV will fail (since 1=0 is never true).
I have blogged about this approach in the past here.
CAUTION: Although I am interested in this approach I have never used it "in anger" in a production database. Careful benchmarking is needed to ensure that the overhead of the full MV refresh whenever the data is changed is not too high.
ERD 继承是 gen-spec 设计模式的经典示例。有很多关于如何在 Oracle 等关系 DBMS 中设计 gen-spec 的文章。你可以通过谷歌搜索“泛化专业化关系建模”找到其中一些。
您将在这些文章中看到的大部分内容已经在对此问题的其他答复中概述。这个话题在《SO》中已经多次出现。有关先前讨论的示例,单击此处。
经典解决方案的主要特点是专用表有一个 id 列,它既是主键又是引用通用表 id 列的外键。以这种方式,子实体不会获得它们自己的身份。您真正需要注意的功能是实现析取的约束。并非所有文章都在其提出的解决方案中强制执行此规则。
ERD inheritance is a classic example of the gen-spec design pattern. There are numerous articles on how to design gen-spec in a relational DBMS like Oracle. you can find some of them by doing a Google search on "generalization specialization relational modeling".
Much of what you will see in these articles has already been outlined by other responses to this question. This topic has surfaced many times in SO. For a sample prior discussion, click here.
The main feature of the classic solution is that the specialized tables have an id column that is both a primary key and a foreign key that references the id column of the generalized table. In this manner, the subentities do not acquire an identity of their own. The feature you really need to watch out for is the constraint that implements disjunction. Not all of the articles enforce this rule in their presented solution.