使用外键时你总是要加入吗?

时间:2016-11-09 20:15:19

标签: mysql sql database database-design relational-database

我不熟悉使用关系数据库,并且对如何查询和连接表有充分的理解。我今天的问题是一个2部分的问题,因为我真的不知道如何用它来表达它。

  1. 通常,将包含大量列的表拆分为"分组数据"是一个好主意。从查询点来看,它可以节省不需要某些数据的时间,并且还可以使其更具可读性。
  2. 例如,通常我会将以下所有列组合到一个表中,然后查询所有数据,即使只使用几列也是如此。我目前正在尝试使用以下数据库结构,这些表将通过uid列进行链接。 :

    上传

    • ID
    • 名称
    • 标题
    • 描述
    • 电子邮件
    • 日期
    • UID

    uploads_exif(除了uid之外的所有内容都是可选的)

    • ID
    • 孔径
    • shutter_speed
    • 相机
    • UID

    uploads_social(除了uid之外的所有内容都是可选的)

    • ID
    • 微博
    • 的Instagram
    • 的flickr
    • URL
    • UID

      1. 如果遵循上面列出的结构,为了查询我需要使用SQL JOINS的所有数据,或者有一种方法可以简单地查询所有表。例如,如果我需要在单个查询中获取上传,uploads_exif和uploads_social,则可以使用另一个函数在不使用JOIN的情况下简单地查询所有这些函数,或者使用JOIN以正确的方式执行此操作。 / LI>

    任何帮助都会非常有用,谢谢!

2 个答案:

答案 0 :(得分:2)

首先,您应该尝试学习Third Normal Form

列数不是主要因素,重要的是尽量避免重复,以便维护变得更容易。

例如,如果你有一个表

employee: [id, first_name, last_name]

你不需要把它分成两个表,好吧这是极端但你明白了。

employee_first: [id, first_name]
employee_last: [id, last_name]

另一种情况是避免重复数据。

如果您有一个字段favorite_fruit而不是使用文本字段,则可以创建一个fk表并保存整数。

   favorite_fruit      favorite_fruit       id  fruit
   orange                 1                  1  orange                 
   orange                 1                  2  apple
   apple          ==>     2                  3  pineapple
   pineapple              3 

节省空间并且易于编辑,例如,如果您希望将orage更改为orange juice,则只需要替换一个。

不确定你的情况是什么,但是例如,如果你有不同类型的upload,你可以拥有一个upload的主表type_id,每个类型可以有一个单独的表细节。

    UPLOAD               |     table: [UPLOAD TYPE1]                     
 upload_id  type_id      | upload_id  [fields unique for type1]  
    xxxx      1      ==> |   xxxxx    ooooooo                 
    yyyy      2          |===================================== 
                         |     table: [UPLOAD TYPE2]
                         | upload_id [fields unique for type2]
                         | yyyyy     oooooooo

另一个例子是员工地址。

无需为building, street, zip code添加多个字段,即可创建三个表

   employee: employee_id
   adress:  address_id, building, street, zip code
   employee_adress: employee_id, adress_id.

这样一个员工可以拥有多个地址,只需添加一个单独的实体address并使用employee分配给employee_adress

答案 1 :(得分:1)

"列的分组和#34;有很多答案。你的问题指出了两个案例;我认为它们很有启发性:

uploads_exif -

  • 1:1主表(uploads)。所以,第一个倾向是说"不要分裂",但......
  • 许多图片没有exif,exif很笨,所有查询都不需要它,所以 将它拆分成一个单独的表是有意义的。
  • 摆脱id,因为uid是唯一的,它可以是PRIMARY KEY。 (这将使JOIN更有效率。)

uploads_social -

  • 1:1主表(uploads)。所以,第一个倾向是说"不要分裂",但......
  • 那真是一个"阵列"东西的。不要在列之间显示数组。
  • 如果列只是真/假标志,则考虑使用SET。 (并把它放在主表中。)
  • 如果列是网址(或类似的东西),那么执行1:多(某种):

更改为

CREATE TABLE uploads_social (
    uid ...,
    which ENUM('facebook', 'twitter', ...),
    url ...,
    PRIMARY KEY(uid, which)
) ENGINE=InnoDB;

(旁白)正常化时,不要过度正常化。不要标准化日期,花车或其他连续的'值。

为什么id中同时包含uiduploads可能你应该摆脱id并将uid提升为PRIMARY KEY