Dan*_*gen 5 mysql database-design relational-database polymorphic-associations
对不起标题,很难解释.
我需要一个与此类似的数据模型:

如您所见,一组可以属于用户或学校.我的问题:它应该只允许属于用户或学校.但绝不是两个在同一时间.
我怎么解决这个问题?
您当前的设计称为独占弧,其中sets表有两个外键,并且只需要其中一个非空.这是实现多态关联的一种方法,因为给定的外键只能引用一个目标表.
另一种解决方案是让一个共同的"超表",无论users和schools引用,然后使用该作为的母公司sets.
create table set_owner
create table users
PK is also FK --> set_owner
create table schools
PK is also FK --> set_owner
create table sets
FK --> set_owner
Run Code Online (Sandbox Code Playgroud)
您可以将其视为与OO建模中的接口类似:
interface SetOwner { ... }
class User implements SetOwner { ... }
class School implements SetOwner { ... }
class Set {
SetOwner owner;
}
Run Code Online (Sandbox Code Playgroud)
你的意见:
所以SetOwner表包含UserID和SchoolID,对吗?这意味着我不会被允许为用户和学校使用相同的ID.我该如何强制执行此操作?
让SetOwners表生成id值.您必须先插入SetOwners,然后才能插入用户或学校.因此,使用户和学校中的ID 不会自动递增; 只需使用SetOwners生成的值:
INSERT INTO SetOwners DEFAULT VALUES; -- generates an id
INSERT INTO Schools (id, name, location) VALUES (LAST_INSERT_ID(), 'name', 'location');
Run Code Online (Sandbox Code Playgroud)
这样,学校和用户都不会使用给定的id值.
如果我想获取集合的所有者类型,我是否需要在SetOwner表中使用ownerType属性?
你当然可以这样做.实际上,可能有其他列对于用户和学校都是通用的,您可以将这些列放在超级SetOwners中.这进入了Martin Fowler的类表继承模式.
如果我想得到学校或用户的名字(无论哪种类型),我可以用一个查询来完成,或者我需要两个查询(首先获取类型,第二个获取名称)?
你需要做一个加入.如果您从给定的Set中查询并且您知道它属于用户(而不是学校),则可以跳过加入SetOwners并直接加入用户.联接不一定要通过外键.
SELECT u.name FROM Sets s JOIN Users u ON s.SetOwner_id = u.id WHERE ...
Run Code Online (Sandbox Code Playgroud)
如果您不知道给定集是属于用户还是学校,则必须对两者进行外部联接:
SELECT COALESCE(u.name, sc.name) AS name
FROM Sets s
LEFT OUTER JOIN Users u ON s.SetOwner_id = u.id
LEFT OUTER JOIN Schools sc ON s.SetOwner_id = sc.id
WHERE ...
Run Code Online (Sandbox Code Playgroud)
您知道SetOwner_id必须匹配一个或另一个表,Users或Schools,但不能同时匹配两者.
| 归档时间: |
|
| 查看次数: |
1912 次 |
| 最近记录: |