PostgreSQL有条件将当前序列值插入另一个字段

时间:2018-07-13 15:15:21

标签: postgresql

问题: 我需要做这样的事情

drop table if exists tt_t;
create temp table tt_t(id serial primary key, main_id int, external_id int);

insert into tt_t(main_id, external_id)
select currval(pg_get_serial_sequence('tt_t', 'id')), 1
where not exists (select from tt_t where external_id = 1);

但是执行会引发错误

  

SQL错误[55000]:错误:在此会话中尚未定义序列“ tt_t_id_seq”的当前时间

解决方案: 有一种方法可以用匿名代码块来解决这个问题

do
$$
begin
    if not exists(select from tt_t where external_id = 1)
    then
        insert into tt_t(external_id, main_id)
        values(1, currval(pg_get_serial_sequence('tt_t', 'id')));
    end if;
end;
$$
;

,但是匿名块有一些限制,例如Dapper parameters not working with PostgreSQL through npgsql connection, is postgres anonymous function parameterization supported?

如何在没有匿名代码块(UPD:并且没有任何DDL更改)的情况下进行修复?

2 个答案:

答案 0 :(得分:1)

可能的解决方案:

insert into tt_t(id, main_id, external_id)
select nextval(pg_get_serial_sequence('tt_t', 'id')), currval(pg_get_serial_sequence('tt_t', 'id')), 1
where not exists (select from tt_t where external_id = 1);

已经向我提出了较短的代码

insert into tt_t(id, main_id, external_id)
select nextval(pg_get_serial_sequence('tt_t', 'id')), lastval(), 1
where not exists (select from tt_t where external_id = 1);

但是我不确定是否将首先计算nextval

答案 1 :(得分:1)

使用默认值怎么办?

drop table if exists tt_t;
create temp table tt_t(id serial primary key, main_id int default lastval(), external_id int);

insert into tt_t(external_id)
select 1
where not exists (select * from tt_t where external_id = 1);

理论上,不可能在nextval()id的那个之间调用另一个lastval()。但是我不确定100%是否有一些我不知道的极端情况。

以下内容也可以工作(即使已经存在一个或多个external_id值)。

insert into tt_t(external_id)
select *
from (values (1),(2),(3)) x (external_id)
where not exists (select * 
                  from tt_t 
                  where external_id = x.external_id);