具有主BELONGS_TO的HAS_MANY的关系数据库设计

时间:2016-09-12 12:30:10

标签: mysql database-design relational-database

我在MySQL工作,但这是一般的关系数据库查询。

我们有一个博客CMS,用户可以在上线后更改博客的网址,我们希望将任何旧博客网址改为301。

我在以下两个表选项之间被撕裂(所有字段都是NOT NULL):

选项1 - 带主标志的HAS_MANY

  • url

    • id(PK)
    • url(UNIQUE)
    • blog_id(FK to blog-id)
    • is_primary(0或1)
  • 博客

    • id(PK)
    • ... 其他字段 ...

缺点:博客没有或有多个主网址时可能存在完整性问题。

优点:许多或一个人的关系结构相似。

选项2 - HAS_MANY和BELONGS_TO混合

  • url

    • id(PK)
    • url(UNIQUE)
    • blog_id(FK to blog-id)
  • 博客

    • id(PK)
    • url_id(FK到主要网址 - 身份证)
    • ... other_fields ...

缺点:博客的url_id和url的blog_id不匹配可能存在诚信问题。

优点:保证每个博客有一个主要网址。

有没有人对这些选项中的任何一个有任何经验,或者可以考虑使用/折扣其中一个或另一个的任何其他理由?或者可能是更好的第三种选择?

更新

刚刚意识到,如果不在网址的blog_id或博客的url_id中允许使用NULL,则选项2无法进行INSERT。

3 个答案:

答案 0 :(得分:1)

而不是上述内容,我会考虑这样的事情:

  • 博客

    • ID
    • url_id
  • URL

    • ID
    • URL
    • redirect_url_id

在这种情况下,redirect_url_id是从url表到其自身的自引用外键。如果网址需要重定向,您可以在此列中添加重定向所需网址的ID。

这样可以避免您在列出的两个选项中注意到的缺点。唯一的缺点是,对于主URL,您只需将redirect_url_id保留为NULL,但这是可以接受的。

无论你做什么,绝对要避免选择2,两个方向的键都是 - 正如你所注意到的那样 - 不可行。

答案 1 :(得分:1)

如果我理解正确,博客通常会有一个网址,它可能会随着时间而改变。您希望保留旧URL,并重定向它。这可能会发生几次,并且可能有几个旧的URL。有时博客没有活动的URL,但它从来没有两个。

让我们从博客开始吧,因为这是我们关心的事情。

create table blog
( id  ... primary key
, url ... unique
);

现在捕获旧网址:

create table url
( blog_id ...
, url ... 
, primary key (blog_id, url)
, foreign key (blog_id) references blog(id)
);

如果blog.url必须为NULL,那就没问题。您只需要处理这样一种可能性:当您将url加入博客时,您可能会获得一个NULL URL来重定向到。使用coalesce的绝佳机会。 ; - )

在您的设计中,据我所知,url.id没有任何实际意义。博客与其URL不同,因此可能需要ID。旧的URL,OTHO,只属于他们曾经属于的博客。给他们一个ID只是给你另一个数字来拖延。

答案 2 :(得分:1)

由于似乎没有关于URL的任何其他数据,为什么要将它放在一个单独的表中?

table blog
  id (PK)
  url (unique)
  ...other_fields..

但是,URL数据可能会发生变化,您希望随时跟踪这些更改。太好了,现在你有理由将它移到一个单独的表中:

table blog
  id (PK)
  ...other_fields..

table URLs
  blogID
  url
  EffDate
  Primary key( blogID, url, EffDate )

使用当前网址显示博客数据:

select  b.ID, u.url, b.* -- the other fields
from    blog b
join    URLs u
    on  u.blogID = b.ID
    and u.EffDate = (
          select  Max( EffDate )
          from    URLs u2
          where   ur.blogID = b.ID
              and ur.EffDate <= @today )
where   b.ID = @MyblogID;

这个查询的好处是,要查看过去任何特定日期的网址,只需将@today替换为您感兴趣的日期。

由于您的应用可能主要对当前网址感兴趣,因此请使用不带where子句的查询创建视图。对于当前的URL,查询将是:

select  *
from    Current_blogs
where   ID = @MyblogID;