当源表中有复合主键时,如何在SQL Server中使用合并
我试图使用MERGE语句从源表更新目标表,但由于SQL试图更新或删除多条记录,因此出现错误。对于后台-我有一个“source”表,它本质上是一个滚动表,记录业务添加的每个数据实例-它只由一个自动递增的“record id”键控。“target”表只能有一个主键实例,即“string”。其思想是查看源表——如果主键匹配,则使用新数据更新所述行,如果不匹配,则插入新行中的所有信息。问题是,我不断收到错误,我试图更新或删除相同的记录两次。我认为这是因为在源表中确实有两个(或更多)字符串实例(主键)。唯一的区别是“添加日期”字段。我如何重新编写此文件以合并这两者?我对这个SQL函数非常陌生,我尝试了一些方法,但都返回了错误。所有这些都归功于另一个用户,他首先给了我合并的建议——我试图使用IF/THEN 我尝试在ON和MATCH子句中使用MAX record date,由于语法原因,这两个子句都返回了错误当源表中有复合主键时,如何在SQL Server中使用合并,sql,sql-server,upsert,Sql,Sql Server,Upsert,我试图使用MERGE语句从源表更新目标表,但由于SQL试图更新或删除多条记录,因此出现错误。对于后台-我有一个“source”表,它本质上是一个滚动表,记录业务添加的每个数据实例-它只由一个自动递增的“record id”键控。“target”表只能有一个主键实例,即“string”。其思想是查看源表——如果主键匹配,则使用新数据更新所述行,如果不匹配,则插入新行中的所有信息。问题是,我不断收到错误,我试图更新或删除相同的记录两次。我认为这是因为在源表中确实有两个(或更多)字符串实例(主键)。唯
MERGE
SCM_Top_Up_Operational O
USING SCM_Top_Up_Rolling R ON (O.String = R.string)
WHEN MATCHED
THEN UPDATE SET
O.Date_Added = R.Date_Added,
O.Real_Exfact = R.Real_Exfact,
O.Excess_Top_Up = R.Excess_Top_Up
WHEN NOT MATCHED BY TARGET
THEN INSERT ( String, Date_Added, Real_Exfact, Article_ID, Excess_Top_Up, Plant)
VALUES (R.String, R.Date_Added, R.Real_Exfact, R.Article_ID, R.Excess_Top_Up, R.Plant);
下面是一些示例数据。如果我查询scm_top_up_rolling for string in('B418496220','B111116220'),我会得到以下结果:
RECORD_ID String Date_Added Real_Exfact Article_ID Excess_Top_Up Plant
----------- ---------- ---------- ----------- ---------- --------------------------------------- -----
3108 B418496220 2019-02-25 2019-05-15 B41849 1235 6220
3211 B418496220 2019-03-28 2019-03-28 B41849 1 6220
3212 B111116220 2019-03-28 2019-03-28 B11111 1 6220
现在,如果我查询scm\u top\u up\u operational以获得相同的字符串:
String Date_Added Real_Exfact Article_ID Excess_Top_Up Plant
---------- ---------- ----------- ---------- --------------------------------------- -----
B418496220 2019-02-25 2019-05-15 B41849 1235 6220
我的目标是使用B418496220的最新条目更新scm_top_up_operational,因为它已经存在于operation表中。然后我想插入B111116220的新记录,因为它在操作表中不存在
希望对您有所帮助,谢谢。您不能在合并语句中直接使用SCM\u Top\u Up\u Rolling,因为用于连接的键(即字符串)需要是唯一的 您需要做的是通过在merge语句的顶部添加几层CTE(公共表表达式)来准备源数据。此步骤的目的是删除重复项并返回唯一的行列表 请看下面的解决方案:
;with cte
as
(
select String, Date_Added, Real_Exfact, Article_ID, Excess_Top_Up, Plant
, row_number() over (partition by String order by Date_Added desc) as 'rank'
from dbo.SCM_Top_Up_Rolling
)
, cte_source
as
(
select *
from cte
where rank = 1
)
merge SCM_Top_Up_Operational O
using cte_source R on (O.String = R.String)
when matched then
update set
O.Date_Added = R.Date_Added,
O.Real_Exfact = R.Real_Exfact,
O.Excess_Top_Up = R.Excess_Top_Up
when not matched by target then
insert ( String, Date_Added, Real_Exfact, Article_ID, Excess_Top_Up, Plant)
values (R.String, R.Date_Added, R.Real_Exfact, R.Article_ID, R.Excess_Top_Up, R.Plant);
查询的关键组件是窗口功能:
row_number()(按日期按字符串顺序划分)作为“秩”
这将生成一个新列排名:
String Date_Added rank
----------------------------
B418496220 2019-02-25 2
B418496220 2019-03-28 1 <= To be used in the merge, e.g. where rank = 1
B111116220 2019-03-28 1 <= To be used in the merge, e.g. where rank = 1
希望答案足够清楚。祝您好运。您可能对表格设计有问题,或者数据处理要求不明确。如果您同时包含表模式和一些示例数据,这将帮助其他人帮助您。我正在添加上面的模式-感谢您的回复添加模式导致我超过了字符数-但我确实添加了一些示例数据
merge SCM_Top_Up_Operational O
using cte_source R on (O.String = R.String)