【问题标题】:Database Question with one-to-many relationship with default具有默认一对多关系的数据库问题
【发布时间】:2019-03-22 17:12:54
【问题描述】:

我有一个用户表和一个地址表。 User 可以有许多地址,因此 Address 表条目有一个 User 的外键。

我的问题是:用户可以有多个地址,但只能将一个标记为主要地址(用于运输目的)。是向名为“main_address”的用户添加一个链接到他的地址之一的外键,还是向名为“is_main”的地址表添加一列更好(默认情况下所有地址为 0,主地址为 1) ?更好的意思是速度和存储方面:)

编辑:按照建议,我将外键添加到用户,但这是有问题的。如果用户和地址还没有在数据库中,那么它会导致循环依赖:没有地址就不能添加用户,没有用户也不能添加地址。谢谢大家!

【问题讨论】:

    标签: mysql database one-to-many default one-to-one


    【解决方案1】:

    user 表上有一个外键,这是可选的以避免相互依赖,从而阻止向其中任何一个添加记录,这可能是更清洁的解决方案。它避免了为一个用户处理多个主地址的问题,占用的空间更少,并使使用主地址信息的连接更简单。

    独特性内置于外键设计。使用“is_main”设计,最简单的预防措施是将字段设为 1 或 null(而不是 1 或 0)并在 (user_id, is_main) 上放置复合唯一键;然后要更改默认值,您必须先将旧默认值设为空,然后再将新默认值设置为 1。

    外键字段占用大约 4 个字节(假设地址为 int pk,忽略可空性); is_main 为用户可能拥有的每个地址占用至少 1 个字节...如果有其他位字段,它可能会更小,但空间问题确实微不足道。

    要获取具有默认地址的用户:

    SELECT * 
    FROM user AS u 
    LEFT JOIN address AS a 
       ON u.main_address_id = a.address_id 
    WHERE u.user_id = ?
    ;
    

    SELECT * 
    FROM users AS u 
    LEFT JOIN address AS a 
       ON u.user_id = a.user_id 
       AND a.is_main = 1 
    WHERE u.user_id = ?
    ;
    

    ...AND is_main = 1 可能看起来是一件微不足道的事情,在很多情况下它会是这样,但在更复杂的查询中,它可能意味着不使用索引。

    然而,is_main 设计的一个好处是:如果您已经有了 user_id 但没有 main_address_id,您可以通过仅从地址表中进行简单(无连接)选择来获取主要地址信息。

    【讨论】:

    • 在第二个查询中它应该是ON u.user_id = a.user_id,因为在这种情况下没有u.default_address_id
    • 啊,是的,我忽略了他们已经为这个领域命名了......不过还是像我的好一点。 ;) 将编辑到 main_address_id
    • 我不是这个意思。如果您有a.is_main,则不需要u.default_address_id
    • 怎么样:insert into address (address_id, user_id) values (9, 1); update users set main_address_id = 9 where user_id = 2? :-)
    • 这有点复杂,我可能会建议CONSTRAINT FOREIGN KEY main_address_fk (user_id, main_address_id) REFERENCES address(user_id, address_id) ON DELETE RESTRICT ON UPDATE RESTRICT;但仅限于限制。但即使这样也感觉有点脏……可能是更新前的触发器,双重检查会更干净。
    猜你喜欢
    • 2020-03-19
    • 1970-01-01
    • 2019-08-31
    • 1970-01-01
    • 2011-11-05
    • 2019-02-15
    • 1970-01-01
    • 2020-10-17
    • 1970-01-01
    相关资源
    最近更新 更多