Sql 与WHERE子句合并
考虑表中存在的数据: 顾客 以及我希望合并到Customers表中的行: 因此,我可以得出近似的伪代码合并语句:Sql 与WHERE子句合并,sql,sql-server,sql-merge,Sql,Sql Server,Sql Merge,考虑表中存在的数据: 顾客 以及我希望合并到Customers表中的行: 因此,我可以得出近似的伪代码合并语句: MERGE Customers USING ( SELECT CustomerID, Name, 'Waiting' FROM Staging) foo ON Customers.CustomerID = foo.CustomerID WHEN MATCHED THEN UPDATE SET Name = foo.Name, Status = foo.Status WH
MERGE Customers USING (
SELECT CustomerID, Name, 'Waiting' FROM Staging) foo
ON Customers.CustomerID = foo.CustomerID
WHEN MATCHED THEN
UPDATE SET Name = foo.Name, Status = foo.Status
WHEN NOT MATCHED BY TARGET THEN
INSERT (Name, Status)
VALUES (Name, Status);
这将合并它们:
| CustomerID | Name | Status |
|------------|-----------------|--------------------|
| 1 | Ian Boyde | Waiting | Last name spelling updated
| 2 | Shelby Blanken | Waiting | Last name changed
| 3 | Jessica Bogden | Waiting | New row added
但只更新一些行
除了一个警告,我不想为已预订的客户更新任何现有行。换句话说,我希望最终结果是:
| CustomerID | Name | Status |
|------------|-----------------|--------------------|
| 1 | Ian Boyde | Waiting | updated existing row spelling
| 2 | Shelby Hawthorn | Booked | not updated because they're booked
| 3 | Jessica Bogden | Waiting | inserted new row
我的第一个猜测是更新包含where子句:
MERGE Customers USING (
SELECT CustomerID, Name, 'Waiting' FROM Staging) foo
ON Customers.CustomerID = foo.CustomerID
WHEN MATCHED THEN
UPDATE SET Name = foo.Name, Status = foo.Status
WHERE Status <> 'Booked' -- <--------- it's the matching row; but don't update it
WHEN NOT MATCHED BY TARGET THEN
INSERT (Name, Status)
VALUES (Name, Status);
但现在该行将不匹配,它们将被插入到“不匹配目标”规则下:
解决这个难题的方法是什么?合并语句由USING子句驱动 使用中与现有行不匹配的行会导致现有行更新。 使用中与现有行不匹配的行将导致创建新行 不在USING子句中的行不能影响数据库中的行 如果不希望更新现有行,请确保其匹配行永远不会进入USING语句中的语句显示的结果集中。这可能意味着在使用中进行连接。这很好 例如:
MERGE Customers USING (
SELECT
s.CustomerID,
s.Name,
'Waiting' as Stat
FROM
Staging s
INNER JOIN Existing e on s.CustomerId = e.CustomerId
WHERE
e.Status <> 'Booked' --ignore all existing booked rows
) foo
...
using语句中的这种连接确保与现有预订行相关的暂存行永远不会进入using语句生成的结果集中。因此,它不能导致update或insert语句由USING子句驱动 使用中与现有行不匹配的行会导致现有行更新。 使用中与现有行不匹配的行将导致创建新行 不在USING子句中的行不能影响数据库中的行 如果不希望更新现有行,请确保其匹配行永远不会进入USING语句中的语句显示的结果集中。这可能意味着在使用中进行连接。这很好 例如:
MERGE Customers USING (
SELECT
s.CustomerID,
s.Name,
'Waiting' as Stat
FROM
Staging s
INNER JOIN Existing e on s.CustomerId = e.CustomerId
WHERE
e.Status <> 'Booked' --ignore all existing booked rows
) foo
...
using语句中的这种连接确保与现有预订行相关的暂存行永远不会进入using语句生成的结果集中。因此,它不能导致更新或插入。关键是要确保记录属于匹配的逻辑,否则它将通过不匹配的逻辑生成新行 为此,我们使用您的代码将您的条件添加到匹配的逻辑中:
MERGE Customers USING (
SELECT CustomerID, Name, 'Waiting' FROM Staging) foo
ON Customers.CustomerID = foo.CustomerID
WHEN MATCHED AND Customers.Status <> 'Booked' THEN
UPDATE SET Name = foo.Name, Status = foo.Status
WHEN NOT MATCHED BY TARGET THEN
INSERT (Name, Status)
VALUES (Name, Status);
这告诉合并匹配CustomerID上的所有内容。当它找到匹配项时,您告诉它仅在状态为“Booked”(已预订)的情况下运行更新。关键是要确保记录符合匹配逻辑,否则它将通过不匹配逻辑生成新行 为此,我们使用您的代码将您的条件添加到匹配的逻辑中:
MERGE Customers USING (
SELECT CustomerID, Name, 'Waiting' FROM Staging) foo
ON Customers.CustomerID = foo.CustomerID
WHEN MATCHED AND Customers.Status <> 'Booked' THEN
UPDATE SET Name = foo.Name, Status = foo.Status
WHEN NOT MATCHED BY TARGET THEN
INSERT (Name, Status)
VALUES (Name, Status);
这告诉合并匹配CustomerID上的所有内容。当它找到匹配项时,您告诉它仅在状态为“Booked”时运行更新
MERGE Customers USING (
SELECT
s.CustomerID,
s.Name,
'Waiting' as Stat
FROM
Staging s
INNER JOIN Existing e on s.CustomerId = e.CustomerId
WHERE
e.Status <> 'Booked' --ignore all existing booked rows
) foo
...
MERGE Customers USING (
SELECT CustomerID, Name, 'Waiting' FROM Staging) foo
ON Customers.CustomerID = foo.CustomerID
WHEN MATCHED AND Customers.Status <> 'Booked' THEN
UPDATE SET Name = foo.Name, Status = foo.Status
WHEN NOT MATCHED BY TARGET THEN
INSERT (Name, Status)
VALUES (Name, Status);