MERGE 意外运行 WHEN NOT MATCHED 子句

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

我正在 SQL Server 中运行 MERGE 语句,其中源表有一行,其 requestMaterialId 与目标表中的行匹配。我的期望是 WHEN MATCHED 子句应该运行,而 WHEN NOT MATCHED 子句应该被忽略,因为源中的 requestMaterialId 与目标中的 id 匹配。

这是我观察到的:

当我删除 WHEN NOT MATCHED 子句时,WHEN MATCHED 子句将按预期执行。 但是,当我包含 WHEN NOT MATCHED 子句时,SQL Server 尝试执行它并尝试在目标表中插入新行,这是我没想到的,因为应该已经存在匹配项。

我已经仔细检查过:

  1. 源和目标都具有相同的 requestMaterialId (4632)。

  2. requestMaterialId 和 id 的数据类型在源和目标之间匹配。

  3. 源查询仅返回一行。

为什么 SQL Server 尝试执行 WHEN NOT MATCHED 子句?关于 MERGE 语句如何确定匹配项,我可能遗漏了什么吗?

表源确实是聚合函数的乘积:

table source

这是 MERGE 查询:

MERGE INTO [nd].[tblRequestMaterial] AS target
USING (
  SELECT
    t1.requestMaterialId,  
    MAX(CASE WHEN t1.novaFieldName = 'productHierarchyId' THEN t1.pushValue END) AS productHierarchyId
  FROM tmp.myTable t1
  WHERE t1.novaTableName = '[nd].[tblRequestMaterial]'
    AND t1.requestMaterialId IN (
      SELECT fc.requestMaterialId
      FROM tmp.FieldCombinations fc
      WHERE fc.fieldCombination = 'productHierarchyId'
    )
  GROUP BY t1.requestMaterialId
) AS source
ON CAST(target.id AS INT) = CAST(source.requestMaterialId AS INT)

WHEN MATCHED THEN
  UPDATE SET [productHierarchyId] = source.productHierarchyId
WHEN NOT MATCHED THEN
  INSERT (id, [productHierarchyId])
  VALUES (source.requestMaterialId, source.productHierarchyId);
sql sql-server azure-sql-database sql-merge
1个回答
0
投票

...当我包含 WHEN NOT MATCHED 子句时,SQL Server 尝试执行它并尝试在目标表中插入新行,这是我没想到的,因为应该已经存在匹配项。

MATCHED 和 NOT MATCHED 并不相互排除 - 存在(或可能存在)匹配和不匹配的行...
请参阅下面的示例

--      S a m p l e    D a t a :  
Create Table tbl_target (id Int, txt Text);
Insert Into tbl_target VALUES( 1, 'Text 1' ), ( 2, 'Text 2' );
Select * From tbl_target;
id txt
1 文字1
2 文字2
--      M e r g e :  
Merge Into tbl_target t
Using
  ( Select 1 as ID, 'Updated 1' as txt Union All
    Select 2, 'Updated 2' Union All
    Select 3, 'Inserted 3' Union All
    Select 4, 'Inserted 4' ) x ON(x.ID = t.ID)
When Matched Then UPDATE SET t.txt = x.txt
When Not Matched Then INSERT VALUES(x.id, x.txt);

--      check the result
Select * From tbl_target;

结果:

id txt
1 更新1
2 更新2
3 插入3
4 已插入4个

小提琴

© www.soinside.com 2019 - 2024. All rights reserved.