J'ai besoin de copier des enregistrements à l'intérieur la même table en changeant un seul champ. Ma table a une séquence générée par défaut entry_id_seq
, Mais je ne suis pas sûr que la colonne id
soit SERIE (comment vérifier cela?).
\d tab
Renvoie juste ceci
Column | Type | Modifiers
-----------------+--------------------------------+------------------------
id | integer | not null
...
Indexes:
"tab_entry_pkey" PRIMARY KEY, btree (id)
Le problème est donc le suivant: lorsque j'essaie de copier un enregistrement de manière simplifiée:
insert into tab_entry select * from tab_entry where id = 3052;
ça jette une erreur
ERROR: duplicate key value violates unique constraint "tab_entry_pkey"
DETAIL: Key (id)=(3052) already exists.
La séquence par défaut ne génère pas la valeur suivante par défaut. Existe-t-il une syntaxe concise permettant d'insérer et de modifier un seul champ sans spécification complète de la table aka FROM tab(col1, col2, col3, ..., col N)
?
La table a de nombreux champs, donc je ne veux pas tous les écrire, car cela affectera la lisibilité du code. Je veux quelque chose comme ça, mais cette syntaxe ne fonctionne pas
insert into tab_entry(id, *) select nextval('seq'), * from tab_entry where id = 3052;
Et cette approche SELECT nextval('seq')
fonctionnera-t-elle s'il y a plusieurs enregistrements à la fois?
La version Psql et Postgres est 9.6.2.
Comme indiqué dans les commentaires, il n'y a pas de syntaxe spéciale pour une telle tâche.
Vous pouvez utiliser une combinaison de fonctions to_json(b)
, json(b)_set
et 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;
Mais je pense que ce n'est pas beaucoup plus simple que d'énumérer toutes les colonnes. Vous pouvez toujours utiliser cette requête relativement simple pour obtenir la liste des colonnes du tableau:
select string_agg(attname,',' order by attnum)
from pg_attribute
where attrelid = 'public.t'::regclass and attnum > 0;