Postgres中的UPSERT语句在分区表上

时间:2012-12-20 21:31:02

标签: postgresql merge partitioning upsert

我有一个分区表和一个更新函数/触发器。更新行时,它首先删除该行,然后将其插入到正确的分区中。我的问题是我试图在Oracle中做类似于MERGE的声明。我发现在Postgres中使用UPSERT的类似实现,如下所示:

WITH upsert as
(
   update mytable2 m 
      set sales=m.sales+d.sales, 
          status=d.status 
   from mytable d 
   where m.pid=d.pid
   RETURNING m.*
)
insert into mytable2 
select a.pid, a.sales, 'NEW' 
from mytable a 
where a.pid not in (select b.pid from upsert b);

然而,问题是更新首先触发 - 导致删除和特定行上的插入,然后插入再次插入它。这是因为我在分区上的更新功能/触发器。是否有任何方法可以像在Oracle中一样使用合并(即,如果找到行,更新它,否则插入它)而不会导致欺骗或在约束违规时失败?

非常感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

这里的问题是在返回null的触发器的交集中,并且upserts期望返回结果。从本质上讲,你所做的是:

  1. 删除行
  2. 插入行
  3. 中止更新(这是你心烦意乱的事情)
  4. 检查更新是否已完成,是否未插入。
  5. 在这种情况下,您会遇到一些问题,因为您的触发器会破坏软件的流程。

    那么如何使这项工作.....

    我没有看到一个简单的方法来使这个工作在一个非常大的集合上。我认为您将不得不将更新部分移动到您可以调用的函数中。该函数的细节将取决于您一次实际更新的行数。那么你可以做INSERT ... SELECT类似于你正在做的事情,但是使用函数调用而不是CTE。