我在关系数据库中遇到了有关水平/垂直分区的问题。
我将举例说明:
我们说我们的人有一个不相交的遗产。一个人可以注册或未注册,但不能同时注册。
一个人与桌子之间也有多对多关系,一个房子可以由一个人拥有,一个人可以拥有一个房子。
如果我然后对Person表进行水平分区,这意味着我们有两个相同的表,但是一个包含已注册的人,另一个包含未注册的人。它如何与多对多关系一起工作?
我还考虑过对这种关系进行分区,但是如果人和其他表之间存在大量的关系,那么水平分区会导致表增长n * 2.这真的是要走的路?
我希望我事先明确表示感谢。
答案 0 :(得分:0)
没有“正确的方法”来做到这一点。有不同的方法有不同的权衡。但是,我会从这样的事情开始:
+------+ +-----+
|Person<----------+House|
+^----^+ +-----+
| |
| |
+---------------++ ++-----------------+
|RegisteredPerson| |UnRegisteredPerson|
+----------------+ +------------------+
Person会有一个自动生成的PersonID。子表RegisteredPerson和UnregisteredPerson将具有相同的主键(使关系1到0或1)。 使用这种方法强制执行只有一个RegisteredPerson或UnRegistered人员的人员有点棘手。最直接的方法是只允许通过维护正确不变量的存储过程对表进行写访问。还有一些方案使用触发器并使用子类型标记Person记录。
答案 1 :(得分:0)
关于术语的说明:在数据库的背景下,&#34;水平&#34;和&#34;垂直&#34;分区通常指的是与您的问题完全无关的存储机制。这是关于继承的问题。
劳伦斯的回答是正确的,就此而言。正如您所描述的那样,您需要一个名为Person
的实体来与House
建立关系。两种方式强制执行“只有一个”#34;注册是将id存储在Person
表中。一种方法是:
create table Person (
. . .
RegisteredId int references RegisteredPersons(RegisteredPersonId),
UnregisteredId int references UnregisteredPersons(UnregisteredPersonId),
check (RegisteredId is null or (UnregisteredId is null)
)
(注意这允许一个人既不是注册也不是未注册,尽管可以修复check
。)
另一种选择是:
create table Person (
. . .
RegType varchar(255),
RegId int
check RegType in ('Registered', 'Unregistered')
)
然后,根据数据库,您可以定义定义外键引用的计算列或视图。像这样:
RegisteredId as (case when RegType = 'Registered' then RegId end),
UnregisteredId as (case when RegType = 'Unregistered' then RegId end),
优点和缺点。第一种方法强制执行外键关系。但是,它会为每种类型占用整数存储空间。对于两种类型,这不是什么大问题。
第二种方法需要跨数据库不标准的功能。例如,在SQL Server和Oracle中,您可以强制执行外键关系 - 但是一个用计算列做,一个用过滤索引做。