是否有一种优雅的方法来处理插入具有重复标识符的行?

时间:2016-11-28 19:49:12

标签: sql postgresql

我正在尝试在我的表中插入一些具有相同唯一标识符的行,但所有其他字段都不同(行表示地图上的点,它们恰好具有相同的名称)。我想最终得到的最终结果是以某种方式修改有问题的行以具有唯一标识符(在标识符上添加一些递增的数字,如“name0”,“name1”,“name2”等)插入命令。

我知道Postgres最近增加了“ON CONFLICT”支持,但这并不是我想要的。

根据Postgres 9.6 Documentation

  

可选的ON CONFLICT子句指定了一个替代操作来引发唯一的违规或排除约束违规错误。对于建议插入的每个单独的行,要么插入,要么......采取替代的conflict_action。 ... ON CONFLICT DO UPDATE更新与建议插入的行冲突的现有行作为替代操作

我想要做的是1)修改有问题的行或插入本身 2)继续插入(而不是用更新替换它,就像ON CONFLICT功能一样)。是否有一种优雅的方式来实现这一目标?或者我是否需要写一些更复杂的东西?

1 个答案:

答案 0 :(得分:0)

你可以这样做:

create table my_table
( 
  name text primary key,
  some_column varchar
);

create sequence my_table_seq;

序列用于为新行的PK列分配唯一的后缀。

"插入了冲突插入修改后的"行为可以这样做:

with data (name, some_column) as (
  values ('foo', 'bar')
), inserted as (
  insert into my_table
  select *
  from data
  on conflict (name) do nothing
  returning *
)
insert into my_table (name, some_column)
select concat(name, '_', nextval('my_table_seq')), some_column
from data
where not exists (select 1 from inserted);

第一次将值插入PK列时,插入(在CTE"插入")就会继续。最终的insert不会插入任何内容,因为where not exists ()会阻止inserted返回一行。

第二次运行时,第一个插入不会插入任何内容,因此第二个(最终)插入将会。

但是有一个缺点:如果"插入" CTE,整体声明将报告" 0行受影响"因为最后的插入是一个"驾驶"此信息。