简体   繁体   中英

Update table via join without key relation

What I have:

Two tables A and B.

A: Col1 Col2 Col3 Col1_Transformed Col2_Transformed

B: Col1 Col2 Col3

They have exact the same columns except some modified data, neither of them have primary key, unique field or whatever (it's extreme case that I need to handle).

Table A contains only part of data from table B. Lets say, I read table B in batches for 10000 rows, then I modify data and write it in to table A (*_Transform columns).

What I need:

I need to update table B using data from table A. It will be easy having primary key or some identity column:

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

But I don't have any.

Next natural guess is to relay on natural key, formed out of 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 

This thing will not work, the reason is in possible NULL value comparation. If target.Col1 or source.Col1 is NULL, than whole record is omitted from update.

Guess #3 (using row number):

I would like to add row_number to table A, it will be my key.

A: row_numb Col1 Col2 Col3 Col1_Transformed Col2_Transformed

And than just join table 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 cannot be used in join clause.

Any ideas how to do it?

Seems like you want NULL to match for the joins, you could do that :

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)) 

Modification of your query with 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 example:

;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 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM