INSERT INTO table FROM SELECT * with nextval() 规范

Sun*_*her 5 postgresql primary-key insert sequence

我需要复制同一个表中的记录只更改一个字段。我的表有默认生成的序列entry_id_seq,但是我不确定id列是 SERIAL(如何检查?)。

\d tab 只返回这个

      Column      |              Type              |            Modifiers            
 -----------------+--------------------------------+------------------------
       id         |             integer            |            not null
...
Indexes:
"tab_entry_pkey" PRIMARY KEY, btree (id)
Run Code Online (Sandbox Code Playgroud)

所以问题是:当我尝试以简化的方式复制记录时:

insert into tab_entry select * from tab_entry where id = 3052;
Run Code Online (Sandbox Code Playgroud)

它抛出错误

ERROR:  duplicate key value violates unique constraint "tab_entry_pkey"
DETAIL:  Key (id)=(3052) already exists.
Run Code Online (Sandbox Code Playgroud)

默认情况下,默认序列不会生成下一个值。是否有任何简洁的语法允许在没有完整表规范的情况下插入和更改单个字段FROM tab(col1, col2, col3, ..., col N)

该表有很多字段,所以我不想把它们都写出来,因为这会影响代码的可读性。我想要这样的东西,但这种语法不起作用

insert into tab_entry(id, *) select nextval('seq'), * from tab_entry where id = 3052;
Run Code Online (Sandbox Code Playgroud)

SELECT nextval('seq')如果一次有多个记录,这种方法是否有效?

Psql 和 Postgres 版本是 9.6.2。

Abe*_*sto 5

如评论中所述,此类任务没有特殊语法。
您可以使用功能组合to_json(b)json(b)_set并且json(b)_populate_record

--drop table if exists t;
create table t(i serial primary key, x int, y text, z timestamp);
insert into t values(default, 1, 'a', now()),(default, 2, 'b', now());

insert into t
select n.*
from t, jsonb_populate_record(
  null::t, 
  jsonb_set(
    to_jsonb(t.*),
    array['i'],
    to_jsonb(nextval('t_i_seq')))) as n;

select * from t;
Run Code Online (Sandbox Code Playgroud)

但我认为它并没有简单得多,然后枚举所有列。您始终可以使用这个相对简单的查询来获取表的列列表:

select string_agg(attname,',' order by attnum)
from pg_attribute
where attrelid = 'public.t'::regclass and attnum > 0;
Run Code Online (Sandbox Code Playgroud)