sql-server - T-SQL:合并插入旧值和新值,然后进行更改
问题描述
这是我第一次使用 T-SQL Merge
,我一直在尝试使用以下条件编写存储过程:
Changes
如果存在记录,则将Id、旧值(更新前)和新值插入表中,然后更新旧值Affected
如果记录不存在,则插入
Changes
Id,旧值和新值为空,然后插入新记录Affected
如果记录不匹配,则插入
Changes
ID、旧值(删除前的值)并作为新值清空,然后删除记录
这是我使用的表格
CREATE TABLE Affected
(
[Id] int IDENTITY(1,1) NOT NULL,
[ZoneId] int NOT NULL,
[Name] varchar(100) NOT NULL,
[Value] varchar(100)
)
CREATE TABLE Changes
(
[AffectedId] int NOT NULL,
[OldValue] varchar(100),
[NewValue] varchar(100)
)
这是我的存储过程,它以两个区域 ID 作为输入参数
CREATE PROCEDURE spAffectChanges
@ZoneId1 int,
@ZoneId2 int
AS
IF(@ZoneId1 < 10)
BEGIN
;WITH fromQ AS
(
SELECT DISTINCT Name, Value
FROM Affected
WHERE ZoneId = @ZoneId1 AND Name NOT IN ('aaa', 'bbb', 'ccc')
), toQ AS
(
SELECT DISTINCT Name, Value
FROM Affected
WHERE ZoneId = @ZoneId2 AND Name NOT IN ('aaa', 'bbb', 'ccc')
)
MERGE toQ
USING fromQ ON (toQ.Name = fromQ.Name)
WHEN MATCHED AND fromQ.Value<>toQ.Value THEN
----first insert
INSERT INTO Changes (AffectedId, OldValue, NewValue)
VALUES(toQ.Id, toQ.Value, fromQ.Value)
----then update
UPDATE SET toQ.Value=fromQ.Value
WHEN NOT MATCHED BY toQ THEN
----first insert
INSERT INTO Changes (AffectedId, OldValue, NewValue)
VALUES(toQ.Id, '', fromQ.Value)
----second insert
INSERT (Name, Zone, Value)
VALUES (fromQ.Name, @ZoneId1, fromQ.Value)
WHEN NOT MATCHED BY fromQ THEN
----first insert
INSERT INTO Changes (AffectedId, OldValue, NewValue)
VALUES(toQ.Id, toQ.Value, '')
----then delete
DELETE
END
有没有办法同时执行插入更改和更新/插入/删除Affected
?
提前致谢
解决方案
您可以使用该OUTPUT
子句来执行此操作。
笔记:
MERGE
需要分号终止符。;WITH
很傻,;
不是起始符,它应该放在每个命令的末尾- 的选项
WHEN NOT MATCHED
是BY SOURCE
和BY TARGET
(这是默认设置) - 我不太明白你是如何
DISTINCT
实现目标的,我不相信这是允许的,也不认为这样做有什么意义。
WITH fromQ AS
(
SELECT DISTINCT Name, Value
FROM Affected
WHERE ZoneId = @ZoneId1 AND Name NOT IN ('aaa', 'bbb', 'ccc')
), toQ AS
(
SELECT Name, Value
FROM Affected
WHERE ZoneId = @ZoneId2 AND Name NOT IN ('aaa', 'bbb', 'ccc')
)
MERGE toQ
USING fromQ ON (toQ.Name = fromQ.Name)
WHEN MATCHED AND fromQ.Value <> toQ.Value THEN
UPDATE
SET toQ.Value = fromQ.Value
WHEN NOT MATCHED BY TARGET THEN
INSERT (Name, Zone, Value)
VALUES (fromQ.Name, @ZoneId1, fromQ.Value)
WHEN NOT MATCHED BY SOURCE THEN
DELETE
OUTPUT inserted.Id, ISNULL(deleted.Value, ''), ISNULL(inserted.Value, '')
INTO Changes (AffectedId, OldValue, NewValue)
;
推荐阅读
- microsoft-graph-api - /teams/allMessages 创建订阅 API 的问题
- mongodb - mongo shell 查询不适用于嵌套文档
- stripe-payments - 如何检索已连接帐户的 Stripe 会话 ID?
- flutter - 编写此飞镖迭代并返回列表的更好方法是什么
- c++ - 为什么字符数组不给出无符号结果
- c++ - 如何将 dll 库链接到我的应用程序?
- javascript - git 中的路径错误,无法在...处创建目录 无效的参数
- python - 如何将表格值从 Web 表单获取到 post 方法 python 烧瓶中?
- c# - 我在 C# 中的表中插入数据时遇到问题
- scikit-learn - 有没有办法在sklearn中导入train_test_spit?