以下代码显示了两个WHEN MATCHED
- 子句。
第一个匹配时只有DATETIME
- 列' updatedAt'改变了。
这应该更新目标,但我不希望在OUTPUT
中标记这一点。第二个匹配在给定匹配中有其他更改时,这应该导致OUTPUT
。
MERGE [Target].dbo.[clients] AS target
USING [Source].dbo.[clients] AS source
ON target.[objectId]=source.[objectId]
WHEN MATCHED AND NOT EXISTS (
SELECT source.firstName, ...
EXCEPT
SELECT target.firstName, ...
) AND source.updatedAt <> target.updatedAt
THEN
UPDATE SET --THIS UPDATE SHOULD NOT LEAD TO AN OUTPUT WITH $ACTION = 'UPDATE'
target.updatedAt = source.updatedAt
WHEN MATCHED AND EXISTS (
SELECT source.firstName, ... , source.updatedAt
EXCEPT
SELECT target.firstName, ... , target.updatedAt
)
THEN
UPDATE SET --THIS UPDATE SHOULD LEAD TO AN OUTPUT WITH $ACTION = 'UPDATE'
target.[firstName]=source.[firstName], ...
WHEN NOT MATCHED BY TARGET
THEN
INSERT ([objectId],[firstName], ... ,[updatedAt]) VALUES ([objectId],[firstName], ... ,[updatedAt])
WHEN NOT MATCHED BY SOURCE
THEN
DELETE
OUTPUT
$ACTION ChangeType
, ISNULL(
inserted.objectId
, deleted.objectId
) AS objectId
, GETDATE() AS DateTimeChanged
;
这可以通过输出所有源列和目标列并将MERGE
放在子查询中来实现,以便在主查询中进行比较,例如:
WHERE NOT (
[ChangeType]='UPDATE'
AND [src objectId]=[tgt objectId]
AND [src firstName]=[tgt firstName]
AND ...
AND [src updatedAt]<>[tgt updatedAt]
)
然而,我觉得应该有更好的方法,因为我能够宣布两个不同的WHEN MATCHED
- 条款。还有更好的办法吗?
答案 0 :(得分:0)
我认为您的示例不正确,因为您有两个条件WHEN MATCHED子句。
根据在线图书:Merge(强调我的意思)
然后匹配时
指定的所有行 * target_table,它匹配ON返回的行,并满足任何其他搜索条件, 根据该条款进行了更新或删除。MERGE语句最多可以具有两个
子句。如果 指定了两个子句,第一个子句必须带有一个 AND子句。对于任何给定的行,第二个WHEN 仅在第一个条件不适用时才应用MATCHED子句。 使用MATCHED子句时,一个必须指定一个UPDATE动作,另一个必须 请指定DELETE操作。 子句,以及超过一行 根据SQL匹配target_table中的一行 服务器返回错误。 MERGE语句无法更新同一行 不止一次,或者更新和删除同一行。
我也尝试过您的代码
BEGIN TRANSACTION
SET XACT_ABORT ON;
CREATE TABLE TargetClients
(
objectId BIGINT
, firstName VARCHAR(50)
, updatedAt DATETIME2(0)
)
CREATE TABLE SourceClients
(
objectId BIGINT
, firstName VARCHAR(50)
, updatedAt DATETIME2(0)
)
go
MERGE TargetClients AS target
USING SourceClients AS source
ON target.[objectId]=source.[objectId]
WHEN MATCHED AND NOT EXISTS (
SELECT source.firstName
EXCEPT
SELECT target.firstName
) AND source.updatedAt <> target.updatedAt
THEN
UPDATE SET --THIS UPDATE SHOULD NOT LEAD TO AN OUTPUT WITH $ACTION = 'UPDATE'
target.updatedAt = source.updatedAt
WHEN MATCHED AND EXISTS (
SELECT source.firstName, source.updatedAt
EXCEPT
SELECT target.firstName, target.updatedAt
)
THEN
UPDATE SET --THIS UPDATE SHOULD LEAD TO AN OUTPUT WITH $ACTION = 'UPDATE'
target.[firstName]=source.[firstName]
WHEN NOT MATCHED BY TARGET
THEN
INSERT ([objectId],[firstName], [updatedAt]) VALUES ([objectId],[firstName], [updatedAt])
WHEN NOT MATCHED BY SOURCE
THEN
DELETE
OUTPUT
$ACTION ChangeType
, ISNULL(
inserted.objectId
, deleted.objectId
) AS objectId
, GETDATE() AS DateTimeChanged
;
rollback
它向我显示了错误
消息10714,第15级,状态1,第33行:类型为“匹配时”的操作 不能在MERGE的'UPDATE'子句中出现多次 声明。
一种可能的解决方案是在Merge_matched
子句中使用CASE语句,并使用一个额外的列作为标志。