SQL Server:将记录外键引用更新为另一个

时间:2019-01-09 07:07:48

标签: sql-server

由于数据迁移的问题,表A中有重复的记录。

表A有两行具有相同名称“ Jason”,其ID为1和3。我想将所有外键引用从Link A和Link B中的id = 3移到1,然后删除Jason的记录,ID = 3,来自表A。

表A

id     name       column2    column3
-------------------------------------
 1     Jason        text      text
 2     Alice        text      text
 3     Jason        text      text   

链接A

id     column1     tableA_ID
----------------------------
 1        text        1     
 2        text        2      
 3        text        3  

链接B

id     column1     tableA_ID
----------------------------
 1        text        1     
 2        text        3      
 3        text        2  

目前,我的简单解决方案是

--update ids
UPDATE db_A.`Link_A` SET id = 1 WHERE tableA_ID = 3;
UPDATE db_A.`Link_B` SET id = 1 WHERE tableA_ID = 3;
--delete ids
DELETE db_A.`Table_A` WHERE id = 3;

生产服务器上有大量受影响的ID,所以我在考虑是否有更好的解决方案。

2 个答案:

答案 0 :(得分:0)

我将获得需要更新的值到临时表中,并使用该值进行所有更新。您可以使用CTE或子查询,但是将其放在#表中对我来说似乎很方便,并简化了更新。因此,请先执行此操作,然后使用#表进行更新:

select a.id originalId, b.minId updatedId
  from Table_A  a
  join (select name, min(id) minId
          from Table_A
         group by name
         having count(*) > 1)  b on a.name = b.name
                                and a.id != b.minId

答案 1 :(得分:0)

我已在临时表中复制了您的DDL,此解决方案看起来不错。 您只需要对tbl B做同样的事情,它应该可以工作。无论如何,请首先在生产表的副本中进行验证:

-- Added DDL for my tables to allow easy testing to everybody:
SELECT * INTO #tblA 
FROM (
    SELECT 1 AS ID, 'Jason' AS [Name], 'text' AS column2, 'text' AS column3
    UNION
    SELECT 2 AS ID, 'Alice' AS [Name], 'text' AS column2, 'text' AS column3
    UNION
    SELECT 3 AS ID, 'Jason' AS [Name], 'text' AS column2, 'text' AS column3
) T1;

SELECT * INTO #tblLinkA 
FROM (
    SELECT 1 AS ID, 'text' AS column1, 1 AS tableA_ID
    UNION
    SELECT 2 AS ID, 'text' AS [Name], 2 AS tableA_ID
    UNION
    SELECT 3 AS ID, 'text' AS [Name], 3 AS tableA_ID
) T1;

SELECT * FROM #tblA;
SELECT * FROM #tblLinkA;
WITH DUP AS (
SELECT *,
    ROW_NUMBER() OVER (PARTITION BY Name, column2, column3 ORDER BY ID) AS Row,
    MIN(ID) OVER (PARTITION BY Name, column2, column3) AS ID_Related
    FROM #tblA) -- SELECT * FROM Dup ORDER BY ID;
UPDATE #tblLinkA
    SET #tblLinkA.tableA_ID = DUP.ID_Related
    FROM DUP
    WHERE  #tblLinkA.tableA_ID = DUP.ID
      and DUP.Row > 1;

WITH DUP AS (
SELECT *,
    ROW_NUMBER() OVER (PARTITION BY Name, column2, column3 ORDER BY ID) AS Row,
    MIN(ID) OVER (PARTITION BY Name, column2, column3) AS ID_Related
    FROM #tblA)
DELETE FROM DUP 
    WHERE Row > 1;
SELECT * FROM #tblA;
SELECT * FROM #tblLinkA;