2014-01-06 70 views
3

我有一个问题,如何更改数据库的模式:数据库体系结构多到多到很多

现在我们已经预定义的表格Categories 和假设表PlacesPeople可分配以类别,所以它看起来是这样的:

People <=> PeopleCategories <=> Categories <=> PlaceCategories <=> Places 

(人们可以有很多种类,类别可以有很多的人,地方可以有很多种类,类别可以有很多地方)

但现在有一个新的要求:

在个人资料显示基于类别(迄今没有问题)的所有相应的地方,并添加一个建模某些属性(例如在前端显示为最喜欢的地方)的勾选框。另一方面,Place profile个人用同一个勾号框标记至少一个同一类别的人。

我不知道是否有一些不错的方式来模拟这个 - 我唯一想到的是添加一个新的PeoplePlaces表,但是我必须手动控制人或地点是否没有改变他们的类别,他们是仍然分配等等 - 我将不得不在应用程序层上管理数据的一致性,这会带来相当大的问题。

我可能做的第二件事就是完全删除类别并仅在PeoplePlaces级别上使用,但我将失去用户的一些简单性:有10个预定义的类别供用户选择,以便People和Places之间的链接是相当自动的前端,只有管理员应该看到哪些地方分配给哪些人,并管理我正在谈论的那个复选框

你对这个架构有何建议?提前致谢! (这是一个MySQL数据库,如果它对某种解决方案很重要,但这是更通用的架构的东西)

+1

这与DBA.SE上的这个问题类似:[是否有DBMS允许引用视图的外键(而不仅仅是基表)?](http://dba.stackexchange.com/questions/17853/are-there-dbms-that-allow-a-foreign-key-that-references-a-view-and-not-only-bas)请阅读所有答案和评论中的讨论,这不是微不足道的实现。 –

+0

@ypercube:是的,正是我所面对的,我看到你提出了这个问题。最后你用了什么?我可能会尝试约束解决方案,因为我的表格可能不会经常更改。谢谢你的链接! – kuncajs

+0

这对我来说更是一个理论问题,而非实际问题。对于MySQL,我想我会使用约束解决方案(这也将需要'PeopleCategories'和'PlaceCategories'表的DELETE触发器或其他方式来定制这两个表上的DELETE操作。) –

回答

2

如果我理解正确你的问题,你需要确保一个人有利于一个地方,与该人自己连接到同一类别?

如果是的话,看看下面的模型:

enter image description here

我们不链接直接“端点”,而是“链接的链接”。这使我们能够将PERSON_CATEGORY.CATEGORY_ID和PLACE_CATEGORY.CATEGORY_ID迁移到FAVORED_PLACE表中,并将它们“合并”,产生一个FAVORED_PLACE.CATEGORY_ID字段(上图中的注释FK1,FK2)。

因此,如果一个人连接到一个地方,必须通过一个共同的类别来完成。此外,因为CATEGORY_ID在PERSON_CATEGORY的PK之外,所以人和地点的特定组合只能使用一次,即使它们通过多个类别匹配也不例外。实际上,你选择一个普通类别为“特殊”。如果某个地点(或人)从特殊类别中删除,则需要选择另一个常用类别作为特殊类别。如果没有公共类别,FAVORED_PLACE中的相应行将不再存在。

+0

我真的很喜欢这种模式,但据我了解,应用程序层还有一些逻辑 - 如果一个人取消了某个类别,我可以填充级联删除但不总是,因为他们可以通过其他类别链接 - 这是什么应用程序必须检查(或者可能触发器可以解决这个问题,但我不允许现在使用它们)。我对吗?感谢您的回答! – kuncajs

+0

它不必位于应用程序层。你可以写一个DELETE过程(用于'Person_Category'表和另一个表的另一个表)来处理它。然后让你的应用程序只执行删除操作来调用这些过程。 –

+0

@kuncajs如果你想移动到不同的“特殊”类别,那么是的,有一些特殊的逻辑(否则你可以在ON DELETE CASCADE上)。如果由于某种原因,您无法将该逻辑封装在触发器中,您仍然可以将其封装为使重用变得容易(如ypercube建议)。 –

0

我不认为删除类别是一个好主意。

你正在做的是引入一个新的实体 - PersonsFavouritePlaces - 直接关联人员和地点,而不是通过类别。明智的做法是PersonsFavouritePlace仅限于按类别链接的Person和Place,所以它应该引用PeopleCategories和PlaceCategories而不是People和Category表。

表看起来像:

create table PeopleFavourtiePlace 
(
    ID int not null, -- Primary key 
    PeopleCategoriesId int not null, -- FK to PK of PerpleCategories 
    PlaceCategoriesId int not null -- FK to PK of PlaceCategories 
) 

我不知道MySQL的是否支持级联删除这样做,但如果是这样两个FK的应该有开启所以当有人取消选择一个类别(删除PeopleCategories行)如果它链接到该类别中最喜欢的地方,它也会被删除。

但是,如果一个人的联系通过多个类别,那么情况就变得复杂的地方....

+0

这太简单了。它允许在此表中添加行,将Person与没有加入类别的地方联系起来。 –