【问题标题】:dynamic database columns?动态数据库列?
【发布时间】:2011-12-07 23:49:31
【问题描述】:

假设我有一个网站,我向用户提供将他的社交网络帐户(如 facebook、twitter 等)与他在我网站上的帐户链接。现在我在网站上支持facebook和twitter,但稍后我会添加更多。所以目前我在数据库中为每个受支持的社交网络都有一个表,例如 Facebook 表,它将包含 facebook 用户 ID 和安全哈希以及我在应用程序中需要的任何内容。该表有一个外键用户 id 到用户表的用户表中,用于网站中的用户。现在假设我想为每个用户知道哪些社交网络与我的网站链接,所以我决定在 varchar 的用户表中添加一列。我会有一个序列,例如上面的例子,如果用户同时链接 facebook 和 twitter 帐户,则值将是 '11',如果他只链接 facebook,则值将是 '10' 等等.这是设计这种东西的好方法吗?

另外,当我想支持一个新的社交网络比如 Google+ 时,我所要做的就是在数据库中添加一个表 GooglePlus 表,然后编写一个脚本,将一个字符添加到现有列中,最初都是用户将拥有他们之前拥有的任何东西 + '0'。所以第一个用户将拥有“110”,第二个用户将拥有“100”。以此类推。

这是我在这种情况下可以采用的最佳方法吗?这是一个可维护的设计吗?

一个澄清问题的例子:

用户表:

User_Id    LinkedSocialNetworks
   1          '100'
   2          '101'

链接的社交网络中的每个字符都代表一个标志,该用户是否将 (1) 他的帐户与指定的社交网络链接 (0)。我知道作为该应用程序的开发者,第一个字符用于 facebook,第二个字符用于 twitter、Google+、....

通过检查用户表,我知道用户 1 正在将他的帐户与 Facebook 关联,用户 2 正在与 Facebook 和 google + 关联,但没有与 twitter 关联。

得到这些信息后,对于用户 1,我将只从 Facebook 表中获取他的信息,对于用户 2,我将从 Facebook 表和 Google+ 中获取他的信息。

顺便说一下我用的是MySql

【问题讨论】:

    标签: mysql database database-design dynamic


    【解决方案1】:

    不,这不是一个好的设计理念。但是,为每个社交网络设置单独的表格并没有错。相反,要将每个帐户关联到不同的人,请尝试如下设计:

    UserID UserName Preferences...
    3      janeDoe123 ...
    4      johnDoe456 ...
    
    FaceBookUsers
    UserID FBUserID FBUserName  ....
    3      234322   janey
    4      3453434  johnperson
    
    MySpaceUsers
    UserID MySpaceUserID MySpaceUname MySpaceThing2  ....
    3      23423234 jj324 ...
    4      323      jps2432dawg ...
    

    您有一个用于在应用程序中使用的用户的通用表,并且该表有一个 uniqueID,它将其他帐户上的其他社交用户身份联系在一起

    这里的想法是,您不必在每次弹出新的社交网络时都添加列,也不必重新计算某些公式并更新公式影响的所有行(这是维护的噩梦)。相反,您只需查询每个表以获取用户的唯一标识符,以查看它们是否存在于该社交网络上。 (例如,由于您的 John Doe 的用户 ID 为 4,您可以通过查询用户 ID 为 4 的行来检查他们是否有 FB 帐户)

    我对此知之甚少,无法告诉您为每个社交网络设置单独的表格是否是个好主意。我不确定是否可以将每个网络的所有详细信息合并到一个表中,但我的直觉是这将是一团糟。我真的不知道这里,所以我不确定你的社交网络一张桌子是否是一个好主意,但我认为这是正确的方法。

    [b]另一种选择[/b] 我不明白您为什么要为指定1010110 之类的关系的位字符串做所有这些工作。您可以使用 MySQL 的 TINYINT(1) 来减少内存占用并执行以下操作:

    UserID UserName Preferences... HasMySpace HasGooglePlus HasFB
    3      janeDoe123 ...             0            1         0
    4      johnDoe456 ...             0            1         0
    

    我认为列默认值(null 或 0)在这里会派上用场。这样,每次弹出新网络时,您都会在主表中添加一个新列,但它可以实现与您当前所拥有的相同的效果,而且工作量要少一些。

    【讨论】:

    • 是的,这可行,但问题是当我想知道用户的链接帐户时,我必须对所有表进行连接!我的设计将让我首先检查 varchar 列并仅加入具有相应 1 的表,例如,如果我的应用程序中有 5 个受支持的社交网络并且用户只是链接他的 Facebook,那么此列将具有value '10000',通过查看这个专栏,我知道我只需要加入 Facebook 表,而不是 5 个表,这样更快
    • 这是非常正确的。让我们考虑弹出一个新的社交网络,就像您在示例中所做的那样。然后,您会为每个用户更新关系列(10100 列)吗?这将是一场维护噩梦。我会稍等一下编辑我的答案...
    • 另一种方法是使用您所拥有的并为您的 10001 逻辑编写代码,如果网络是 FB、MySpace、Google+,并且您的字符串是 10,那么用户显然没有 google+ 帐户(字符串不够长)。这样一来,您就无需在弹出新网络时更新每一行。
    • 或者,您可以在每次弹出新网络时一直使用的大用户表中添加一列(默认值为 NULL 或 0),并使用单个列而不是一个字符串1010001。 MySQYL 没有 BIT 类型,但它有 TINYINT ,您可以将其指定为 TINYINT(1) 并且比 BIT 占用更多空间,但小于 INT 类型。
    • 我想过,但是在数据库中添加一个新列不仅很难在数据库中维护,而且在代码本身也很难维护,因为我必须修改代码,对吧?跨度>
    【解决方案2】:

    我宁愿有类似的东西

    CREATE TABLE users (id INT NOT NULL auto_increment PRIMARY KEY, ... );
    CREATE TABLE social_networks (id INT NOT NULL auto_increment PRIMARY KEY, 
     name varchar(50), ...);
    CREATE TABLE users_social_networks (user_id INT NOT NULL, 
     social_network_id INT NOT NULL, social_id VARCHAR(100) NOT NULL, 
     social_name VARCHAR(100), 
      PRIMARY KEY (user_id, social_network_id), 
      UNIQUE(social_network_id, social_id), 
       FOREIGN KEY (user_id) REFERENCES users(id), 
      FOREIGN KEY (social_network_id) REFERENCES social_networks(id));
    

    【讨论】:

      猜你喜欢
      • 2019-06-22
      • 2013-06-10
      • 1970-01-01
      • 2015-07-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-18
      • 1970-01-01
      相关资源
      最近更新 更多