【问题标题】:INSERT based on the relationship between the types of entities to be inserted?INSERT 基于要插入的实体类型之间的关系?
【发布时间】:2021-08-30 19:04:39
【问题描述】:

我找不到我正在尝试做的事情的术语,这可能会限制我查找与我的问题相关的信息的能力。

我正在尝试将产品标识符和产品处理代码(图中的橙色表)与基于流程类型的每个流程代码有效的产品类型和子类型验证相关联。重要的是,每个产品标识符都与产品类型相关(参见ProductIdentifier 表),每个流程代码与流程类型相关(参见ProcessCode 表)。我将下表中的属性最小化为我的问题所必需的属性。

在上面的例子中,当我INSERT INTORunProcessTypeOne 表时,我需要验证RoleOneProductIdentifierProductCode 是否存在于ProductTypeTwo 中。同样,我需要验证RoleTwoProductIdentifierProductCode 是否存在于ProductSubtypeOne 中。

当然,我可以使用在运行SELECT 后插入RunProcessTypeOne 表的存储过程来检查相关表中是否存在与RoleOneProductIdentifierRoleTwoProductIdentifier 相关的ProductCode。这似乎不是最优的,因为我必须为每个INSERT 运行三个SELECTs。另外,ProcessTypes 和 ProductCodes 之间的关系只能在存储过程中知道,而不是通过表本身之间建立的关系(外键)知道,这似乎很可疑。

这种方法有替代方案吗?是否有处理此类验证的标准,您需要根据实体类型之间的关系(例如 ProductTypeTwoProcessTypeOne 之间的关系)验证实体类型的单个实例(例如 ProductIdentifiers)?

如果更多详细信息有帮助:ProductCodeProcessCode 之间的关系是多对多的,但在每个流程中都有定义产品角色的规则,并且只有某些产品类型或子类型可以满足这些角色。 ProductTypeOne 可能包含定义特定类型产品的属性,例如颜色或形状。 ProductIdentifier 包括许多已生产的ProductCodeProcessCode 包括放在机器上进行处理的设置。 ProductType 通过ProductCode 确定ProductIdentifier 是否对特定的ProcessType 有效。单个ProcessCodes 不会区分有效的ProducIdentifiers,只有与ProcessCode 相关的ProcessType 会区分。

【问题讨论】:

  • 您是否研究过条件约束?对我来说听起来像这个问题。 stackoverflow.com/questions/44867149/…
  • 为什么ProductCodeProductIdentifier两者都有//它们有什么区别?为什么表RunProcessTypeOne 使用ProductIdentifier 作为FK/不能使用ProductCode?在我看来ProductCode 是关联产品信息的主要方式(?),而ProductIdentifiers 是某种“替代键”(?)也许并非所有产品都有ProductIdentifierProductCode是一个稳定的密钥(?)然后RunProcessTypeOne应该有一个FK到ProductCode not ProductIdentifier.
  • @AntC ProductIdentifier 包括ProductCode 的各个实例。假设我为ProductCode =“jie530”的每个规格生产两个木块。这些木块中的每一个都有一个单独的ProductIdentifier,比如“123”和“456”。 RunProcessTypeOne 必须包含 ProductIdentifier,因为每个 ProductIdentifier 都有唯一的值,例如日期、操作员、空气温度、重量。所有产品都有ProductCodeProductIdentifier

标签: mysql sql


【解决方案1】:

ProcessTypesProductCodes 之间的关系只能在存储过程中知道,而不是通过表本身之间建立的关系(外键)知道,这似乎很可疑。

是的,这是一个重要的观察结果,很高兴看到您质疑当前架构。事实上,SQL 在表示数据结构方面并不是很强大。因此,存储过程通常是唯一/最差的方法。

我会就如何在没有存储过程的情况下实现这一点提出建议,但我不会称之为“最佳”:INSERTs 的性能可能会受到影响(UPDATEs 的性能可能会更糟) ,因为 SQL 引擎实际上可能会执行与您在存储过程中编码相同的SELECTs。

将表 ProductIdentifier 拆分为两个:

  • ProductIdentifierTypeTwoPKProductIdentifier,ProductCodeFKREFERENCESProductTypeTwo.ProductCode.

  • ProductIdentifierTypeOnePKProductIdentifier,ProductCodeFKREFERENCESProductTypeOne.ProductCode.

  • 还有CREATE VIEWProductIdentifierUNION这两个子表,PKProductIdentifier。这可以确保ProductIdentifier 在两种类型之间不会重复。

IOW 这避免了ProductIdentifier 表直接引用ProductCode 表,它只能将ProductType 作为列值检查,而不是作为引用结构。

然后

  • RunProcessTypeOne.RoleOneProductIdentifierFKREFERENCESProductIdentifierTypeTwo.ProductIdentifier.

  • RunProcessTypeOne.RoleTwoProductIdentifierFKREFERENCESProductIdentifierTypeOne.ProductIdentifier.

将原始的 ProductIdentifier 设为 VIEW 是管理更新的最不理想的方式(我从您的评论中猜测):ProductIdentifiers 的波动性低于 RunProcesses。

关于您的更一般的问题:

是否有处理此类验证的标准,您需要根据实体类型之间的关系(例如 ProductTypeTwoProcessTypeOne 之间的关系)验证实体类型的单个实例(例如 ProductIdentifiers)?

SQL 标准中包含一些工具。大多数供应商还没有实现它们,或者只是部分支持它们 - 主要是因为实现它们需要运行 SELECTs 并在表更新过程中使用棘手的逻辑。

  • 您应该能够使用过滤器CREATE VIEW 仅针对某些 FK 的目标行。 (您的 dba 可能会反对 VIEWs 带来了不可接受的性能影响。在此示例中,您将有一个 ProductIdentifier 表,我在上面建议的两个子表为 VIEWs。但是维护这些视图需要加入 ProductCode 以按 ProductType 过滤。)
  • 那么您应该能够为VIEW 而不是基表定义一个FK。 (这是许多 SQL 供应商不支持的部分。)

【讨论】:

  • 谢谢。我不认为 MySQL 会让我 FK 到VIEW。我确实需要一个包含所有ProductIdentifiers 的表,因为一些RunProcess 有一个接受任何ProductType 的角色(属性)。为了解决这个问题,我可以有一个基表 ProductIdentifier 与您建议的子类型表,但如下所示:ProductIdentifierTypeTwo PK,FK ProductIdentifier REFERENCES ProductIdentifier.ProductIdentifier, ProductCode FK REFERENCES ProductTypeTwo.ProductCode .我没有想到这一点,因为常见的属性,例如ProductCode,通常存储在基表中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-08-11
  • 2013-03-27
  • 2012-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多