简体   繁体   中英

SQL Server 2014 - MainTable & TempTable - IF Not Exists Insert Else Update

I have two tables with same columns on Microsoft SQL Server 2014.

MainTable and TempTable.

I would like to enter the updated / fresh data from TempTable onto MainTable avoiding duplicates.

The MainTable looks like the following:

在此处输入图片说明

The TempTable looks like the following:

在此处输入图片说明

The data in the TempTable will constantly change. It may have updated data or new rows.

What I am trying to achieve is, insert / update the data from TempTable onto MainTable.

TempTable : - In this example, The row with Numbr 101 and 104 has the updated data. It also has new rows with Numbr 105 and 106 . I would like to update the data of 101 and 104 and also insert 105 and 106.

Please advice as I am new to SQL.


UPDATE1:

After using the following query:

--Insert New
INSERT INTO MAINTABLE
SELECT A.*
FROM 
TempTable as A 
LEFT JOIN MainTable as B
ON B.Number = A.Number
WHERE B.Number IS NULL

--Update Old
UPDATE A
SET A.Number = B.Number,
    A.Name = B.Name,
    A.LastActive = B.LastActive,
    A.Country = B.Country
FROM 
TempTable as A 
LEFT JOIN MainTable as B
ON B.Number = A.Number
WHERE B.Number IS NOT NULL

The Output of MainTable :

在此处输入图片说明

It worked, but when the data in TempTable is updated and new data is added:

在此处输入图片说明

The Result after running the query:

MainTable and TempTable respectively

在此处输入图片说明

The new Row 108 got added (From TempTable --> MainTable ) but the updated Row 106 had no effect and the value in TempTable got copied from MainTable.

INSERT INTO MAINTABLE
SELECT A.*
FROM 
TempTable as A 
LEFT JOIN MainTable as B
ON B.Number = A.Number
WHERE B.Number IS NULL

--Update Old
UPDATE A
SET A.Name = B.Name,
A.LastActive = B.LastActive,
A.Country = B.Country
FROM TempTable as B 
INNER JOIN MainTable as A
 ON B.Number = A.Number
WHERE A.Name <> B.Name,
 A.LastActive <> B.LastActive,
 A.Country <> B.Country

I'm assuming that Numbr is a key or unique field in both tables. If that's not the case, then you should not use these queries. Additionally, the field should be indexed in both tables if performance is a problem.

This is the simplest way:

BEGIN TRANSACTION;
INSERT INTO MainTable (Numbr, Name, LastActive, Country)
SELECT t.Numbr, t.Name, t.LastActive, t.Country
FROM TempTable t
WHERE NOT EXISTS (SELECT 1 FROM MainTable m WHERE m.Numbr = t.Numbr);

UPDATE m
    SET Name = t.Name,
        LastActive = t.LastActive,
        Country = t.Country
FROM MainTable m
INNER JOIN TempTable t
    ON m.Numbr = t.Numbr
WHERE m.Name <> t.Name
    OR m.LastActive <> t.LastActive
    OR m.Country <> t.Country;
COMMIT;

Note that if Name, LastActive, or Country are nullable fields then the syntax gets much more verbose. For example, if all three fields are nullable, then you should use this syntax:

BEGIN TRANSACTION;
INSERT INTO MainTable (Numbr, Name, LastActive, Country)
SELECT t.Numbr, t.Name, t.LastActive, t.Country
FROM TempTable t
WHERE NOT EXISTS (SELECT 1 FROM MainTable m WHERE m.Numbr = t.Numbr);

UPDATE m
    SET Name = t.Name,
        LastActive = t.LastActive,
        Country = t.Country
FROM MainTable m
INNER JOIN TempTable t
    ON m.Numbr = t.Numbr
WHERE m.Name <> t.Name
    OR (m.Name IS NULL AND t.Name IS NOT NULL)
    OR (m.Name IS NOT NULL AND t.Name IS NULL)
    OR m.LastActive <> t.LastActive
    OR (m.LastActive IS NULL AND t.LastActive IS NOT NULL)
    OR (m.LastActive IS NOT NULL AND t.LastActive IS NULL)
    OR m.Country <> t.Country
    OR (m.Country IS NULL AND t.Country IS NOT NULL)
    OR (m.Country IS NOT NULL AND t.Country IS NULL);
COMMIT;

If you absolutely need to minimize the number of writes, then you should break up the UPDATE statement into one query for each field. This may run faster or may run slower, so just because you're writing less doesn't mean the queries will execute faster. Again, I've assumed there are no nullable fields in your system:

BEGIN TRANSACTION;
INSERT INTO MainTable (Numbr, Name, LastActive, Country)
SELECT t.Numbr, t.Name, t.LastActive, t.Country
FROM TempTable t
WHERE NOT EXISTS (SELECT 1 FROM MainTable m WHERE m.Numbr = t.Numbr);

UPDATE m
    SET Name = t.Name
FROM MainTable m
INNER JOIN TempTable t
    ON m.Numbr = t.Numbr
WHERE m.Name <> t.Name;

UPDATE m
    SET LastActive = t.LastActive
FROM MainTable m
INNER JOIN TempTable t
    ON m.Numbr = t.Numbr
WHERE m.LastActive <> t.LastActive;

UPDATE m
    SET Country = t.Country
FROM MainTable m
INNER JOIN TempTable t
    ON m.Numbr = t.Numbr
WHERE m.Country <> t.Country;
COMMIT;
--Insert New
INSERT INTO MAINTABLE
SELECT A.*
FROM 
TempTable as A 
LEFT JOIN MainTable as B
ON B.Number = A.Number
WHERE B.Number IS NULL

--Update Old
UPDATE A
SET A.Number = B.Number,
    A.Name = B.Name,
    A.LastActive = B.LastActive,
    A.Country = B.Country
FROM 
TempTable as A 
LEFT JOIN MainTable as B
ON B.Number = A.Number
WHERE B.Number IS NOT NULL

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