我在Web服务中有一个SQL proc,它接受一组用户数据并执行以下操作:
最后一部分(WHEN NOT MATCHED BY SOURCE THEN UPDATE
)存在问题,表中的每一行都更新为archived=1
。我假设只有customerId
与@customerId
匹配的行会受到影响,但会更新除ON
中匹配的行以外的所有行,并忽略ON
过滤器。
MERGE
[tbl_Users] AS tgt -- Target
USING
#tbl_working AS src -- Source
ON
(tgt.customerID = @customerId) AND
(tgt.employeeID = src.EmployeeId)
WHEN MATCHED THEN UPDATE SET -- user exists; update
tgt.username = src.username
tgt.name = src.FirstName
WHEN NOT MATCHED BY TARGET THEN INSERT -- user does not exist; create
(
customerID,
username,
name
)
VALUES
(
@customerId,
src.UserName,
src.Name
)
WHEN NOT MATCHED BY SOURCE THEN UPDATE -- user no longer required; archive
SET tgt.archived = 1;
我可能没有正确使用最后一部分,所以请欣赏任何输入。
答案 0 :(得分:2)
您可能只想添加额外条件:
WHEN NOT MATCHED BY SOURCE AND tgt.customerID = @CustomerID
THEN UPDATE -- user no longer required; archive
SET tgt.archived = 1;
ON
子句仅用于确定source
和target
的匹配方式。到WHEN ...
条款时,它已经完成了它的工作。它并没有留下来并且有选择地适用于其他任何事情。
可能有助于意识到MERGE
语句可能会影响target
表中的每一行。
让我们说发生的事情是我们将source
表拆分为两组行 - sm
是通过{target
表中的行匹配的行{1}}子句,ON
是su
中的所有剩余行。
我们还说我们还将source
表拆分为两组行 - target
是与tm
表和source
中的行匹配的行是tu
中所有剩余的行。
target
子句正在处理行集WHEN MATCHED
和sm
,并确定如何处理这些行。
tm
正在处理行WHEN NOT MATCHED IN TARGET
。
su
正在处理行WHEN NOT MATCHED IN SOURCE
。
您不需要将tu
条件添加到AND tgt.customerID = @CustomerID
,因为该条件已用于确定WHEN MATCHED
中的哪些行以及su
中的哪些行}(以及sm
和tu
)。
你做希望在tm
子句中有这个额外条件,因为你实际上想要进一步划分WHEN NOT MATCHED
集合而不影响所有这些行。
您可能需要考虑的另一个选择是您可以先过滤目标表,然后对其应用合并:
tu
现在上面讨论的关于;WITH CustomerUsers as (
SELECT * FROM tbl_Users where customerID = @customerID
)
MERGE
CustomerUsers AS tgt -- Target
USING
#tbl_working AS src -- Source
ON
(tgt.employeeID = src.EmployeeId)
...
的所有内容实际上只涉及target
中属于tbl_Users
"