通过连接更新表而没有关键关系

时间:2014-11-17 16:36:08

标签: sql-server join sql-update row-number

我有什么:

两张表A和B.

A: Col1 Col2 Col3 Col1_Transformed Col2_Transformed

B: Col1 Col2 Col3

除了一些修改过的数据之外,它们具有完全相同的列,它们都没有主键,唯一字段或其他(我需要处理的极端情况)。

表A仅包含表B中的部分数据。 可以说,我批量读取表B中的10000行,然后修改数据并将其写入表A(* _Transform列)。

我需要什么:

我需要使用表A中的数据更新表B. 拥有主键或某些标识列很容易:

UPDATE target
SET  target.Col1 = source.__Col1
FROM B target
join A as source 
ON  target.Id = source.Id  

但我没有。

接下来的自然猜测是继续使用Col1 Col2 Col3形成的自然键。

UPDATE target
SET  target.Col1 = source.__Col1
FROM B target
join A as source 
ON  target.Col1 = source.Col1  AND 
    target.Col2 = source.Col2  AND 
    target.Col3 = source.Col3 

这个东西不起作用,原因是可能的NULL值比较。如果target.Col1或source.Col1为NULL,则从更新中省略整个记录。

猜#3(使用行号):

我想将row_number添加到表A,它将是我的密钥。

答:row_numb Col1 Col2 Col3 Col1_Transformed Col2_Transformed

而不仅仅是加入表B:

UPDATE target
SET  target.Col1 = source.__Col1
FROM B target
join A as source 
ON  ROW_NUMBER() OVER(ORDER BY target.Col1,target.Col2,target.Col3) = source.ROW_NUMB  

Bur row_nubmer不能在join子句中使用。

任何想法怎么做?

2 个答案:

答案 0 :(得分:1)

好像你希望NULL匹配联接,你可以这样做:

UPDATE target
SET  target.Col1 = source.__Col1
FROM B target
join A as source 
ON  (target.Col1 = source.Col1 OR (target.Col1 IS NULL AND source.Col1 IS NULL)) AND -- most reliable way to do it
    ISNULL(target.Col2,'-1') = ISNULL(source.Col2,'-1')  AND -- less reliable but more concise, replace -1 by any data that cannot be in the tables
     (target.Col3 = source.Col3 OR (target.Col3 IS NULL AND source.Col3 IS NULL)) 

答案 1 :(得分:0)

使用ISNULL

修改您的查询
UPDATE target
SET  target.Col1 = source.__Col1
FROM B target
join A as source 
ON  IsNull(target.Col1,'') = IsNUll(source.Col1,'')  
    AND IsNull(target.Col2,'') = IsNull(source.Col2,'')  
    AND IsNull(target.Col3,'') = IsNull(source.Col3,'') 

CTE示例:

;With CTETableA 
AS
(
Select Col1,Col2,Col3,Col1_Transformed,Col2_Transformed
       ROW_NUMBER() OVER(ORDER BY Col1,Col2,Col3) id
       from A
),
CTETableB
As
(
Select Col1,Col2,Col3,ROW_NUMBER() OVER(ORDER BY Col1,Col2,Col3) id
       from B
)

UPDATE target
SET  target.Col1 = source.Col1
FROM CTETableB target
join CTETableA as source 
ON  target.Id = source.Id  

Insert into B(Col1)
Select Col1 from CTETableB