SQL合并关联记录

时间:2011-09-19 23:29:38

标签: sql merge

假设我们有一个包含许多其他关联表的表的数据库。如果您绘制了数据库的图表,那么这将是中心的表格,其中有许多外键关系。它突然出现。

为了使其更具体,让我们说这个中心表中的两个记录是 Initech Contoso 。 Initech和Contoso都与关联表中的许多其他记录相关联,例如 Employees AccountingTransactions 等。假设两者合并(Initech购买了Contoso)并且从数据的角度来看,它真的就像合并所有记录一样简单。获取所有Contoso相关记录的最简单方法是什么,让它们指向Initech,然后删除Contoso?

使用CASCADE的更新非常接近,但是如果不关闭约束然后重新打开(yuck),它显然无法工作。

有没有一个很好的通用方法来做到这一点,而不是搜索每个链接表并逐个迁移它们?这必须是一个共同的要求。它出现在这个项目的两个地方,可以总结为:实体A需要控制实体B当前控制的所有内容。我怎样才能实现呢?

合并前:

Companies
ID Name
1  Contoso
2  Initech

Employees
ID Name CompanyId
1  Bob  1 
2  Ted  2

合并后:

Companies
ID Name
2  Initech

Employees
ID Name CompanyId
1  Bob  2 
2  Ted  2

我所有的搜索尝试都只提出了关于合并单独数据库的问题......很抱歉,如果之前已经提出这个问题。

3 个答案:

答案 0 :(得分:1)

此查询可能依赖于供应商,但在MySQL中:

UPDATE Employees e, Cars c, OtherEntity o
  SET e.CompanyId = 2, c.CompanyId = 2, o.CompanyID = 2
  WHERE e.CompanyID = 1 OR c.CompanyId = 1 OR o.CompanyId = 1;

答案 1 :(得分:0)

简洁,不;没有通用的方法来做到这一点。

使用表Companies,Employees,Departments和AccountingTransactions来考虑您的示例数据库。

您需要删除其中一条公司记录(因为在合并之后,您只会记录当前的事务状态。)

您需要更改员工记录以更改雇用公司。但是,两家公司的员工编号很可能是N,其中一个(可能是Contoso)必须分配一个新的员工编号。

您可能面临的问题是Conotoso数据中的部门1是工程部门,但Initech的部门是财务部门。因此,您需要担心如何在两家公司之间映射部门编号,然后您面临将Contoso员工分配给Initech部门的问题。

对于历史会计事务,您可能必须将Contoso的历史会计记录保存为Contoso的名称,而某些(最新的)事务将需要迁移到Initech的名称。因此,也许您不会从公司表中删除Contoso记录,但您将无法使用它来识别任何新记录。

这些只是为什么这些映射无法轻易实现自动化的一小部分原因。

答案 2 :(得分:0)

不,没有简单的通用方法可以合并行并在整个系统中级联这些更改。您可以编写所有脚本 - 这可能是最佳方式,具体取决于您的方案 - 或设计解决方法。

一种解决方法可能是在中央表上实现父项模式(或将其抽象到另一个表)。然后你会得到像

这样的东西
Companies 
ID ParentID Name 
1  2        Contoso 
2  null     Initech  

Companies 
ID ParentID Name 
1  3        Contoso 
2  3        Initech  
3  null     MegaInitech

并且您加入此中央Companies表的所有查询现在都会检查ID和ParentID;

SELECT * 
FROM Employees          
WHERE CompanyId IN (SELECT ID FROM Companies WHERE ID = @id OR ParentID = @ID)

将其抽象为视图或函数

CREATE FUNCTION fn_IsMemberOf
(
    @companyId INT,
    @parentId INT
)
RETURNS BIT
AS
BEGIN   
    DECLARE @result BIT = 0
    SELECT @result = 1 FROM Companies 
    WHERE ID = @companyId
        AND COALESCE(ParentID, ID) = @parentID
    RETURN @result
END

SELECT * 
FROM Employees          
WHERE fn_IsMemberOf(CompanyId, 1) = 1

(没有测试过,但你明白了)

相关问题