如何将 INSERT 和 UPDATE 语句分组到“MERGE”语句中

问题描述 投票:0回答:1

我一直在尝试将 INSERT 和 UPDATE 语句分组到一个“MERGE”语句中,条件如下:

  • 密钥:location_cd、machine_cd、product_cd
  • 如果当前记录的状态为0,则输入数据的状态为1,则插入一条新记录,并将[lastest_flag]列的值从“1”更新为“0”。
  • 否则,只需更新当前记录的状态即可。

示例表:表A

位置_cd machine_cd 产品_cd 状态 最新_标志 更新时间戳
0012345678 1234567890 123456 1 1 2024/06/10 15:30:15
0012345678 1234567890 111111 0 1 2024/06/10 15:30:15

输入数据:输入1

位置_cd machine_cd 产品_cd 状态 更新时间戳
0012345678 1234567890 123456 0 2024/06/10 15:40:15

输入数据:输入2

位置_cd machine_cd 产品_cd 状态 更新时间戳
0012345678 1234567890 111111 1 2024/06/10 15:40:15

预期输出:

  • 对于 input1,我们将使用 UPDATE 语句。
  • 使用 input2,我们将插入新记录并更新当前记录的状态。
位置_cd machine_cd 产品_cd 状态 最新_标志 更新时间戳 行动
0012345678 1234567890 123456 0 1 2024/06/10 15:40:15 更新
0012345678 1234567890 111111 0 0 2024/06/10 15:30:15 更新
0012345678 1234567890 111111 1 1 2024/06/10 15:40:15 新记录

我尝试过这个,但不起作用。

  1. 定义输入数据

    DECLARE @input_data table(
        location_cd varchar(10) NOT NULL,
        machine_cd varchar(10) NOT NULL,
        product_cd varchar(6) NOT NULL,
        status varchar(1) NOT NULL,
        updated_timestamp varchar(20) NOT NULL
    );
    
    Insert into @input_data
    VALUES ('0012345678','1234567890','123456','0','2024/06/10 15:40:15'),
        ('0012345678','1234567890','111111','1','2024/06/10 15:40:15')
    
  2. 这是我的带有 MERGE 语句的 SQL。当我运行它时,我收到错误:

    错误 156 关键字“BEGIN”附近的语法不正确

    MERGE INTO tableA AS Target
    Using @input_data AS Source
    ON Target.location_cd = Source.location_cd
    AND Target.machine_cd = Source.machine_cd
    AND Target.product_cd = Source.product_cd
    WHEN MATCHED AND Target.status = 1 AND Source.status = 0 AND Target.updated_timestamp < Source.updated_timestamp THEN
        UPDATE SET
             Target.status = Source.status,
             Target.updated_timestamp = Source.updated_timestamp
    WHEN MATCHED AND Target.status = 0 AND Source.status = 1 AND Target.updated_timestamp < Source.updated_timestamp THEN
        BEGIN
            INSERT (machine_cd,location_cd,product_cd,status,lastest_flag,updated_timestamp)
            VALUES (Source.machine_cd,Source.location_cd,Source.product_cd,Source.status,'1',Source.updated_timestamp);
            UPDATE SET Target.lastest_flag = '0';
        END;
    
sql sql-server
1个回答
0
投票

不可能在

MERGE
语句中为每个合并行指定多个操作。每行只能执行一项操作。您最多只能有两个
WHEN MATCHED
子句,其中一个必须具有
UPDATE
,另一个必须具有
DELETE
,因此您必须将它们压缩在一起。总而言之,最终你甚至不需要
MERGE
,你可以使用普通的连接
UPDATE

但是,您可以使用

OUTPUT
子句将数据输出到同一个表或另一个表中。但是
OUTPUT
在整个语句上只指定一次,因此您要么需要输出到另一个表变量,然后从那里有条件地插入,或者您可以执行两个单独的语句,只有一个带有
OUTPUT

UPDATE t
SET
    status = s.status,
    updated_timestamp = s.updated_timestamp
FROM tableA AS t
JOIN @input_data AS s
  ON t.location_cd = s.location_cd
 AND t.machine_cd = s.machine_cd
 AND t.product_cd = s.product_cd
WHERE t.status = 1
  AND s.status = 0
  AND t.updated_timestamp < s.updated_timestamp;


UPDATE t
SET lastest_flag = '0'  -- why is this a string?

OUTPUT
    s.machine_cd, s.location_cd, s.product_cd, s.status, '1', s.updated_timestamp
INTO tableA
    (machine_cd, location_cd, product_cd, status, lastest_flag, updated_timestamp)

FROM tableA AS t
JOIN @input_data AS s
  ON t.location_cd = s.location_cd
 AND t.machine_cd = s.machine_cd
 AND t.product_cd = s.product_cd
WHERE t.status = 0
  AND s.status = 1
  AND t.updated_timestamp < s.updated_timestamp;
© www.soinside.com 2019 - 2024. All rights reserved.