首页 > 解决方案 > 如何在目标与源不匹配的特定日期删除合并语句中的行

问题描述

我有一个合并语句,每天都会运行新数据,因为每天都会将新数据转储到我的表中,这是我的代码示例:

MERGE SQL_Backup as Target 
USING Temp as Source 
ON target.code = source.code 
WHEN MATCHED THEN update SET 
target.saledate = source.saledate, 
target.branchcode = source.branchcode 

WHEN NOT MATCHED BY TARGET 
THEN insert ( 
code, saledate
) 
values ( 
source.code, source.saledate 
)

    when not matched by source
      then delete;

但是,这会删除我的整个表,我只希望它删除今天添加的行,不应触及任何以前的行。

这是源表和目标表的图像:

源/目标表

我有一个标记为“saledate”的列,其中包含转储数据的日期,并且我有一个标记为“代码”的唯一列,用于合并以检测重复项。

想知道是否有一个 time 与 saledate = today 的来源不匹配,然后删除或其他什么?

标签: sqltsqlazure-sql-databaseazure-sql-server

解决方案


MERGE 语句允许在“WHEN NOT MATCHED BY SOURCE”子句中仅使用目标的列和比较术语范围内的列。

例如,如果您想按目标表中的日期进行过滤,那么 MERGE 适合您的情况,但如果您想按源表的日期进行过滤,那么这不适合 MERGE

这是一个使用简单表的完整示例

DROP TABLE IF EXISTS S
DROP TABLE IF EXISTS T
GO
CREATE TABLE S(
    id int,
    DT DATE
)
DROP TABLE IF EXISTS T
GO
CREATE TABLE T(
    id int,
    DT DATE
)

INSERT T(id, DT) values (1,'2000-01-01'),(2,'2000-01-01'),(3,'2019-01-01')
INSERT S(id, DT) values (3,'2000-01-01'),(4,'2000-01-01'),(5,'2019-01-01')
GO

SELECT * FROM T
SELECT * FROM S
GO

-- the following query will raise an error
MERGE T as Target USING S as Source
    ON Target.id = Source.id

    WHEN MATCHED THEN 
        UPDATE SET Target.id = Source.id + 1000
    WHEN NOT MATCHED BY TARGET THEN 
        insert (id, DT) values (Source.id, Source.DT)
    -- Only target columns and columns in the clause scope are allowed in the 'WHEN NOT MATCHED BY SOURCE' clause of a MERGE statement.
    -- Using the bellow wil raise an error:
     WHEN NOT MATCHED BY SOURCE AND Source.DT > '2005-01-01' THEN DELETE;
GO

-- the following query will work well
MERGE T as Target USING S as Source
    ON Target.id = Source.id

    WHEN MATCHED THEN 
        UPDATE SET Target.id = Source.id + 1000
    WHEN NOT MATCHED BY TARGET THEN 
        insert (id, DT) values (Source.id, Source.DT)
    -- The bellow will work OK, since I use condition on the TARGET
    WHEN NOT MATCHED BY SOURCE AND TARGET.DT > '2005-01-01' THEN DELETE;
GO

SELECT * FROM T
SELECT * FROM S
GO

推荐阅读