(tldr;我认为定期更新会强制表使用自然键。所以我必须迁移我的数据库模式。)
我有一个带有像 planets 这样的表的生产数据库,虽然它具有很好的潜在自然键(例如,从未真正改变的行星名称),但使用典型的递增整数作为主键。行星表有一个或两个自引用列,例如* parent_planet_id *。
现在我正在建立离线的基于云的工作人员,每周重新创建行星记录的子集,并且他们需要与主服务器集成。我的计划是:
这最后一步是我不知道如何解决。我不是每次都完全取代行星表,所以问题是两个数据库都有自己的递增整数PK。所以我不能只做一个简单的导入。
我考虑过没有id列的导出,但后来我意识到自引用列阻止了这一点。
我看到两种可能的解决方案:
答案 0 :(得分:1)
修改Planets
以使用替代层次结构技术,例如 nested sets ,关闭表或路径枚举而不是出口。这将打破ID依赖。
或者,如果您仍然不喜欢这个想法,请将导出和导入视为ETL问题。
PlanetName, ParentPlanetName
PlanetNames
)ParentPlanetName
)在任何情况下,来自第一个数据库的代理键都不应该离开该数据库 - 它没有任何意义。
答案 1 :(得分:0)
最佳解决方案(就设计而言)将是改进您的密钥架构并实现一些复合密钥,其中包含有关导入行星的时间和地点的信息,但您不希望这样做。
更容易(我认为),但有点“快乐的工程”解决方案是修改导入密钥。你可以这样做,例如: 1.锁定主系统中的行星表(因此在导入过程中不会出现新的键), 2.创建具有两列的查找表,基于主系统中行星表的ID和PLANET NAME, 3.从该表中获取最大键值, 4.通过添加在步骤#3中重新获得的MAX值,递增每个导入的密钥(识别和引用父子行星关系)值, 5.更改主星球表并更改当前自动增量值以获得实际MAX + 1值 6.现在查看表(过程中的光标循环),检查当前行星名称是否在查找中有不同的键,如果是,则首先从查找中删除表中的记录(旧的)并更新当前检查的行中用于旧ID的密钥值(即更新), 7.打开桌子。
答案 2 :(得分:0)
大多数操作都是更新
所以你需要一个“真正的”合并。换句话说,您必须确定一个正确的订单,您可以在其中插入/更新数据,因此在此过程中不会违反FK。
我不确定parent_planet_id
是什么意思,但假设它意味着“轨道”而“行星”这个词也被拉伸以包含卫星,想象一下你的主数据库中只有火球,火星和Deimos需要进口。这只能按特定顺序进行:
parent_planet_id
设置为指向火星。parent_planet_id
所以它指向火星。虽然您可以交换步骤(2)和(3),但在步骤(1)之前无法做到。
您需要递归下降来确定正确的顺序,然后比较自然键 1 以查看需要UPDATEd和INSERTed的内容。不幸的是,MySQL不支持递归查询,所以你需要手动完成。
我不太清楚代理键如何在这个过程中起作用 - 如果有的话,它们会增加一个你最终需要协调的间接层。
1 与代理人不同,它在不同的数据库中是有意义的。您不能只比较自动递增的整数,因为相同的整数值可能会识别不同数据库中的不同行星 - 您将有错误的UPDATE。另一方面,GUID永远不会匹配,即使行描述同一行星 - 你也会有错误的INSERT。