Search code examples
sqlsql-servert-sqlsql-server-2017sql-merge

Merge not inserting new values


I'm trying to use MERGE to insert new values to a table only if they don't already exists in the same table.

This is the query I am using:

MERGE [dbo].[TARGET_TABLE] AS Target 
USING 
(SELECT [NAME]
    FROM [dbo].[TARGET_TABLE] 
    WHERE [NAME]='ThisValuesDoesntExists' AND [STATUS] IS NULL) AS Source
    ON Target.[NAME]= Source.[NAME]
WHEN NOT MATCHED
    THEN INSERT ([NAME],[file_first_upload],[upload_date])
        VALUES('ThisValuesDoesntExists',1,DEFAULT);

But when I execute it, I get a (0 rows affected) message.

If I execute the "Source" query, I get 0 rows.

SELECT [NAME] 
FROM [dbo].[TARGET_TABLE] 
WHERE [NAME] = 'ThisValuesDoesntExists' AND [STATUS] IS NULL

What am I doing wrong?

Thanks


Solution

  • If you look at the MERGE documentation, you will see that the source data must exist in order to match (or not match) against existing rows in the target table:

    WHEN NOT MATCHED [ BY TARGET ] THEN <merge_not_matched>

    Specifies that a row is inserted into target_table for every row returned by <table_source> ON <merge_search_condition> that doesn't match a row in target_table, but satisfies an additional search condition, if present. The values to insert are specified by the <merge_not_matched> clause. The MERGE statement can have only one WHEN NOT MATCHED [ BY TARGET ] clause.

    The problem you're facing is that your "source" data is not returning anything and so the MERGE query has nothing to match against or insert.

    Sample code below to demo:

    IF OBJECT_ID('dbo.TARGET_TABLE', 'U') IS NOT NULL DROP TABLE dbo.TARGET_TABLE 
    GO 
    
    CREATE TABLE TARGET_TABLE ([Name] VARCHAR(100), file_first_upload BIT, upload_date DATETIME, [STATUS] VARCHAR(100)) 
    
    MERGE [dbo].[TARGET_TABLE] AS Target 
    USING 
    (SELECT [NAME]
        FROM [dbo].[TARGET_TABLE] 
        WHERE [NAME]='ThisValuesDoesntExists' AND [STATUS] IS NULL) AS Source
        ON Target.[NAME]= Source.[NAME]
    WHEN NOT MATCHED
        THEN INSERT ([NAME],[file_first_upload],[upload_date])
            VALUES('ThisValuesDoesntExists',1,DEFAULT);
    
    SELECT * 
    FROM TARGET_TABLE 
    
    MERGE [dbo].[TARGET_TABLE] AS Target 
    USING (VALUES ('ThisValuesDoesntExistss',1,GETDATE())) AS Source ([Name], [file_first_upload],[upload_date])
    ON Target.[NAME] = Source.[Name] 
    WHEN NOT MATCHED
        THEN INSERT ([NAME],[file_first_upload],[upload_date]) VALUES (Source.[Name], Source.file_First_upload, Source.upload_date);
    
    SELECT * 
    FROM TARGET_TABLE