2016-03-30 29 views
1

对我来说,阻止用户或错误代码插入无效数据似乎是合理的,但我不记得在任何地方看到这个!复杂的mysql约束外键

考虑以下表 enter image description here

  • 我怎样才能确保订单总是引用由同一用户创建的地址?
  • 这种约束通常和推荐?我的意思是,我在设计中甚至不得不关心它吗?
+1

用户可以插入多个地址? –

+0

@Sougata,是的,只是一个实例!但是让我们考虑一下,您可以将订单交付到您的工作场所或家中或...... – azerafati

+0

复杂的“业务逻辑”应该编码在用户和数据库之间的代码层中。 –

回答

1

因为我不希望用户能够下订单没有一个有效的地址,因此我只是将单独的FK删除到用户表,并使用从用户组合的用户ID - 地址ID字段地址表作为外键。

CREATE TABLE orders AS (
    --[COLUMN DEFINITIONS] 
    address_id BIGINT NOT NULL, 
    user_id BIGINT NOT NULL, 
    CONSTRAINT fk_usr_addr FOREIGN KEY (user_id, address_id) 
         REFERENCES address(user_id, id) 
) ENGINE=InnoDB; 

如果订单是不完整的,没有地址还没有,那么这不应该是一个多列外键的问题,根据MySQL文档using foreign keys因为:

比赛子句在SQL标准中控制 组合(多列)外键中的NULL值与主键 进行比较时如何处理。 MySQL本质上实现了 MATCH SIMPLE定义的语义,它允许外键全部或部分为NULL。 在这种情况下,包含这种外键的(子表)行允许插入 ,并且与引用的 (父)表中的任何行都不匹配。使用 触发器可以实现其他语义。

+0

不错的建议!谢谢,但是我还没有设置地址的未完成订单,以及如果用户决定随时删除他的某个地址会发生什么? – azerafati

+0

订单完成后不应更改。因此,如果用户想要更改或删除已完成订单中的地址,则必须创建一个新地址记录或将地址标记为在yor地址表中删除,但不要实际删除该地址。另一种解决方案是不使用地址作为外键,而是将其内容复制到订单中。在这种情况下甚至不会有地址表的外键。您可以使用此场景的触发器来强制执行数据完整性。 – Shadow

+0

明白了,谢谢。 – azerafati