设计与表A,表B或表A和表B相关的SQL表的最佳实践是什么?

时间:2017-05-22 19:56:06

标签: mysql sql database-design

我们说我有三张桌子。我将使这些表格尽可能简单,以说明设计问题:

用户:

CREATE TABLE users (user_id INT PRIMARY KEY);

网络:

CREATE TABLE networks (network_id INT PRIMARY KEY);

网络用户:

CREATE TABLE network_users (
     network_id INT, 
     user_id INT, 
     PRIMARY KEY(network_id, user_id), 
     FOREIGN KEY(network_id) REFERENCES networks(network_id), 
     FOREIGN KEY(user_id) REFERENCES users(user_id)
);

如上所示,用户与网络有很多关系,如网络用户表中所述。到目前为止,这一切都非常传统。

现在我的问题是:

我想说我想添加一个消息表,我希望能够存储发送到的消息:

  1. 特定用户
  2. 特定网络,
  3. 或网络中的用户
  4. 消息表的最佳设计方法是什么?

    我可以构建一个这样的消息表:

    CREATE TABLE messages (
        message_id INT PRIMARY KEY, 
        network_id INT, 
        user_id INT, 
        FOREIGN KEY(network_id) REFERENCES networks(network_id), 
        FOREIGN KEY(user_id) REFERENCES users(user_id)
    );
    

    其中:

      发送给特定用户的
    1. 消息设置了user_id字段,而network_id字段为NULL
    2. 发送到特定网络的
    3. 消息的network_id字段设置为user_id
    4. 为NULL 发送给网络内用户的
    5. 消息同时设置了network_id和user_id字段
    6. 但这是最好的方法吗?由于network_id和user_id字段可能为null,因此我必须创建一个单独的主键(message_id),而不是使用复合主键(network_id和user_id),否则将会这样做。

3 个答案:

答案 0 :(得分:1)

您在问题中描述的内容称为多态关联。请查看this article,其中介绍了一些可能的建模方法。

虽然本文描述了如何以最一般的方式建模多态关联,但我认为您的方法也很好,因为大多数人可能不会拥有超过3种消息类型(对用户而言,对网络而言)以及网络中的用户

答案 1 :(得分:1)

我看到的一种方法是在messages中加entity_type以及user,其中类型告诉您记录是指network还是{{1}}(或稍后的其他类型)。 This response有一些处理这种情况的有趣例子。

答案 2 :(得分:0)

如果你在3件事(A,B,C)中有很多:很多关系:

CREATE TABLE ABC (
    a_id ...,
    b_id ...,
    c_id ...,
    PRIMARY KEY(a_id, b_id, c_id),
    INDEX(b_id, c_id, a_id),
    INDEX(c_id, a_id, b_id)
) ENGINE=InnoDB;

索引允许您从任何表格到其他表格。

但是......在确定这是最好的之前,让我们看一下你的SELECTs