SQL Server 为什么MERGE for UPSERT不适用于空表?

5jvtdoz2  于 2023-01-04  发布在  其他
关注(0)|答案(2)|浏览(138)

事实表(目标)是空的(没有行)。当我执行下面的代码时,它不适用于插入,只适用于更新。

merge into fact as f
using (select * from fact where date_id = 429 and region_id = 432 and attack_id = 5
and target_id = 11 and gname_id = 12 and weapon_id = 12 and success = 1 and claimed = 1 and ishostkid = 0 ) as t
on (f.date_id = t.date_id and f.region_id = t.region_id and f.attack_id = t.attack_id and f.target_id = t.target_id and
f.gname_id = t.gname_id and f.weapon_id= t.weapon_id and f.success = t.success and f.claimed = t.claimed and f.ishostkid = t.ishostkid)
when MATCHED then
    update set num_attack = f.num_attack + 1
when not matched by target then
    insert values (429,432,5,11,12,12,1,1,0,1);

既然没有匹配(空表)如何插入数据?
当存在行且匹配时,该命令工作正常。
这只是一个示例代码,值由?使用python和ODBC模块动态更改。

2w3kk1z5

2w3kk1z51#

您可以重新安排查询,使源使用values子句,也就是. Table Value Constructor ...

merge into fact as f
using (
  select * from (values
    (429,432,5,11,12,12,1,1,0,1)
  ) vals (date_id, region_id, attack_id, target_id, gname_id, weapon_id, success, claimed, ishostkid, num_attack)
) as t
on (f.date_id = t.date_id and f.region_id = t.region_id and f.attack_id = t.attack_id and f.target_id = t.target_id and
f.gname_id = t.gname_id and f.weapon_id= t.weapon_id and f.success = t.success and f.claimed = t.claimed and f.ishostkid = t.ishostkid)
when MATCHED then
    update set num_attack = f.num_attack + 1
when not matched by target then
    insert values (date_id, region_id, attack_id, target_id, gname_id, weapon_id, success, claimed, ishostkid, num_attack);
gywdnpxw

gywdnpxw2#

对于UPSERT,您需要一个构造的值表,而不是 actual 表,例如,只需选择如下所示的新值(或使用VALUES子句),则始终存在匹配或不匹配的行,并相应地进行更新或插入。

merge into Fact as f -- target
using (
  select 429 as date_id
    , 432 as region_id
    , 5 as attack_id
    , 11 as target_id
    , 12 as gname_id
    , 12 as weapon_id
    , 1 as success
    , 1 as claimed
    , 0 as ishostkid
) as t -- source (the 't' alias could be confusing here)
on (
  f.date_id = t.date_id
  and f.region_id = t.region_id
  and f.attack_id = t.attack_id
  and f.target_id = t.target_id
  and f.gname_id = t.gname_id
  and f.weapon_id = t.weapon_id
  and f.success = t.success
  and f.claimed = t.claimed
  and f.ishostkid = t.ishostkid
)
when matched then
    update set num_attack = f.num_attack + 1
when not matched by target then
    insert values (t.date_id, t.region_id, t.attack_id, t.target_id, t.gname_id, t.weapon_id, t.success, t.claimed, t.ishostkid, 1);

相关问题