数据库设计循环引用/潜在不一致

时间:2018-01-31 23:51:08

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

我无法想出摆脱这种潜在不一致的方法:

考虑这4个实体:

     CUSTOMERS  >----------------   LOCATIONS
      id                             id
      name                           name
      loc_id           
                                       |
       |                               |
       |                               |
       |                               |
       /\                              /\

      ORDERS   >------------------   PRODUCTS           
       c_id                           id
       p_id                           name
                                      loc_id

每个CUSTOMER都有一个LOCATION(id:" 3&#34 ;, name:" US")

每个CUSTOMER订购许多产品,每个产品都可以被许多客户购买(这些交易存储在ORDERS表中)

每个产品仅适用于具有相同位置的客户 ("美国"客户可以访问“美国”产品)

问题:

我想只为客户提供产品,因此我在" US“中添加产品,因此我在loc_id&中插入产品 #34; 3" (US)。

当我使用loc_id&#34; 2&#34;插入客户时出现问题。 (EU)并为同一产品创建订单。我最终在一个 LOCATION 中找到客户 订购 产品,其他 LOCATION < / strong>即可。有什么方法可以避免这种情况吗?

1 个答案:

答案 0 :(得分:0)

  

当我使用loc_id&#34; 2&#34;插入客户时出现问题。 (欧盟)并为同一产品创建订单。我最终与一位客户在一个LOCATION订购了一个不同位置的产品。有什么方法可以避免这种情况吗?

有两种方法可以添加此限制。在您的架构中,或在model

在架构中,您可能会在订单表上使用触发器来确保客户位置和产品位置相同。

在模型中,您可以在订单模型中添加逻辑,以在创建订单之前验证客户位置和产品位置是否相同。并且您确保创建订单的所有内容都使用模型,而不是无所事事地进行SQL查询。出于其他维护原因,您也希望这样做。

放在哪里?模型还是架构?我的答案是模型。这就是我的想法......

架构用于数据完整性。模型适用于业务规则。

推论:&#34;业务规则&#34;包括大多数数据验证。

&#34;客户和订单必须具有相同的位置&#34;是业务规则。它是业务定义的限制,可以随时更改。

相比之下,每个产品必须有一个有效的位置&#34;或者&#34;您无法删除包含订单的产品&#34; 数据完整性问题。如果products.loc_idnull或指向不存在的一行位置,则会发生错误。这就是not nullreferences以及cascade之类的内容。

业务规则一直在变化,因此您需要一种快速且易于更改的解决方案。

架构价格昂贵且风险很大。任何更改都可能会影响使用数据库的所有内容。触发器是不透明和复杂的。 SQL也受限于它可以做什么样的验证。检查相等性是一回事,但它可以检查URL是否有效吗?这个词不是一个咒骂词吗?由于存在这些限制,您最终会面临在架构和模型之间拆分验证和业务规则的压力,从而存在干扰和混乱的风险。

相比之下,该模型易于更改和测试。它可以快速响应业务规则的奇思妙想。编程语言更适合于所有数据验证,许多模型库都具有丰富的验证功能。有些人甚至会自动将这些转换为架构约束。

业务规则和数据验证变得复杂

此外,就数据而言,业务规则是任意的外部限制。如果您将其放入架构中,那么与数据交互的所有内容都必须具有此限制: 无例外 。这意味着您在架构中放置的任何业务规则都必须处理所有可能性。

业务规则往往很简单,但随着时间的推移变得越来越复杂。触发器和约束不是为复杂性而设计的。将业务规则放在架构中会限制业务的可能性,因为规则不能轻易表示为触发器。

相比之下,模型是用编程语言编写的,可以很好地处理复杂性。也许是美国和美国加拿大需要分组?还是欧盟国家?也许有些客户为国际运费支付额外费用?用任何体面的编程语言编写的模型都可以处理所有这些额外的复杂性。

如果不是所有东西都使用该模型怎么办?存储过程。

这些天我们倾向于编写模型并使用工具然后为我们编写模式。并且预计与数据库的所有交互都将通过模型进行。但情况并非总是如此。如果数据验证在模型中,那么使用数据库的不是模型的东西呢?

我的第一个答案是:考虑不这样做。如果异构系统需要访问数据,请考虑使用micro-service作为数据库上的抽象层。然后,需要使用数据的其他系统通过定义良好的API与之交互。这样可以避免每个人都无所事事地抓住数据库,也不会知道谁在使用数据做什么。

如果您不能这样做,请考虑使用存储过程的混合方法。将存储过程写为模型的一部分。他们处理与数据库的交互并完成所有CRUD工作。在您的情况下,您要编写一个new_order存储过程,该过程执行模型将执行的所有验证。然后,任何与数据库交互的人都将使用存储过程而不是编写自己的查询。

许多数据库甚至允许使用其他语言编写的存储过程,从而为您提供全方位的灵活性。不幸的是,MySQL没有。如果您刚刚开始进步,请考虑切换到更强大的数据库,例如PostgreSQL。

结论

您正在谈论的数据验证类型是一项业务规则。业务规则一直在变化,它们往往比触发器和约束可以处理的更复杂。它们属于模型,它们更容易更改,并且功能更强大的验证工具。

一定要有模特。