it-swarm.com.de

INSERT INTO-Tabelle FROM SELECT * mit der Spezifikation nextval ()

Ich muss Datensätze kopieren innerhalb dieselbe Tabelle, die nur ein Feld ändert. Meine Tabelle hat die standardmäßig generierte Sequenz entry_id_seq, Ich bin mir jedoch nicht sicher, ob die Spalte id SERIAL ist (wie kann ich das überprüfen?).

\d tab Gibt genau dies zurück

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

Das Problem ist also: Wenn ich versuche, Datensätze auf vereinfachte Weise zu kopieren:

insert into tab_entry select * from tab_entry where id = 3052;

es wirft Fehler

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

Die Standardsequenz generiert standardmäßig keinen nächsten Wert. Gibt es eine präzise Syntax, die das Einfügen und Ändern eines einzelnen Feldes ohne vollständige Tabellenspezifikation oder FROM tab(col1, col2, col3, ..., col N) ermöglicht?

Die Tabelle enthält viele Felder, daher möchte ich nicht alle schreiben, da dies die Lesbarkeit des Codes beeinträchtigt. Ich möchte so etwas, aber diese Syntax funktioniert nicht

insert into tab_entry(id, *) select nextval('seq'), * from tab_entry where id = 3052;

Und funktioniert dieser SELECT nextval('seq') Ansatz, wenn mehrere Datensätze gleichzeitig vorhanden sind?

Psql und Postgres Version ist 9.6.2.

3
Suncatcher

Wie in den Kommentaren erwähnt, gibt es für eine solche Aufgabe keine spezielle Syntax.
Sie können eine Kombination von Funktionen verwenden to_json(b), json(b)_set und 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;

Aber ich denke, es ist nicht viel einfacher, als nur alle Spalten aufzuzählen. Sie können diese relativ einfache Abfrage immer verwenden, um die Spaltenliste der Tabelle abzurufen:

select string_agg(attname,',' order by attnum)
from pg_attribute
where attrelid = 'public.t'::regclass and attnum > 0;
4
Abelisto