我正在 SQL Server 中运行 MERGE 语句,其中源表有一行,其 requestMaterialId 与目标表中的行匹配。我的期望是 WHEN MATCHED 子句应该运行,而 WHEN NOT MATCHED 子句应该被忽略,因为源中的 requestMaterialId 与目标中的 id 匹配。
这是我观察到的:
当我删除 WHEN NOT MATCHED 子句时,WHEN MATCHED 子句将按预期执行。 但是,当我包含 WHEN NOT MATCHED 子句时,SQL Server 尝试执行它并尝试在目标表中插入新行,这是我没想到的,因为应该已经存在匹配项。
我已经仔细检查过:
源和目标都具有相同的 requestMaterialId (4632)。
requestMaterialId 和 id 的数据类型在源和目标之间匹配。
源查询仅返回一行。
为什么 SQL Server 尝试执行 WHEN NOT MATCHED 子句?关于 MERGE 语句如何确定匹配项,我可能遗漏了什么吗?
表源确实是聚合函数的乘积:
这是 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);
...当我包含 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个 |