Ich konvertiere zum ersten Mal in meinem Leben eine MySQL-Tabelle in PostgreSQL und stürze mich in das traditionelle Neuling-Problem, kein auto_increment zu haben.
Nun habe ich herausgefunden, dass die Postgres-Lösung eine Sequenz verwendet und dann bei jedem Einfügen nextval () dieser Sequenz als Standardwert anfordert. Ich habe auch gelesen, dass der SERIAL-Typ automatisch eine Sequenz und einen Primärschlüssel erzeugt, und dass nextval () den Zähler sogar dann erhöht, wenn er innerhalb von Transaktionen aufgerufen wird, um zu verhindern, dass die Sequenz gesperrt wird.
Was ich nicht finden kann, ist das Problem, was passiert, wenn Sie manuell Werte in ein Feld mit einer UNIQUE- oder PRIMARY-Einschränkung und einer nextval () einer Sequenz als Standard einfügen. Soweit ich das sehe, führt dies dazu, dass INSERT fehlschlägt, wenn die Sequenz diesen Wert erreicht.
Gibt es eine einfache (oder gebräuchliche) Möglichkeit, dies zu beheben?
Eine klare Erklärung würde sehr geschätzt werden.
Update: Wenn Sie das Gefühl haben, ich sollte das nicht tun, werden Sie nie in der Lage sein, dies zu beheben oder machen Sie einige fehlerhafte Annahmen, bitte fühlen Sie sich frei, sie in Ihren Antworten zu zeigen. Sag mir vor allem, was ich stattdessen tun soll, um Programmierern eine stabile und robuste Datenbank zu bieten, die nicht mit einer einfachen Einfügung beschädigt werden kann (vorzugsweise ohne alles hinter gespeicherten Prozeduren zu verstecken)
Wenn Sie Ihre Daten migrieren, würde ich die Sequenzbeschränkung für die Spalte löschen und alle Ihre Einfügungen ausführen. Verwenden Sie setval () , um die Sequenz auf den maximalen Wert Ihrer Daten zu setzen und dann Ihre Spaltensequenz nextval () als Standard wiederherzustellen.
Um Tometzkys großartige Antwort zu erweitern, hier eine allgemeinere Version:
%Vor%Was Sie auf jede Spalte anwenden können, sagen Sie test.id, also:
%Vor% Sie können einen Trigger erstellen, der überprüft, ob currval('id_sequence_name')>=NEW.id
.
Wenn Ihre Transaktion nicht den Standardwert oder nextval('id_sequence_name')
verwendet hat, wird eine Funktion currval
einen Fehler auslösen, da sie nur funktioniert, wenn die Sequenz in der aktuellen Sitzung aktualisiert wurde. Wenn Sie nextval
verwenden und dann versuchen, einen größeren Primärschlüssel einzufügen, wird ein weiterer Fehler ausgelöst. Eine Transaktion wird dann abgebrochen.
Dies würde verhindern, dass irgendwelche schlechten Primärschlüssel eingefügt werden, die die serielle Verbindung unterbrechen würden.
Beispielcode:
%Vor%Das Einfügen mit dem Standardprimärschlüssel funktioniert dann gut:
%Vor%Aber das Einfügen eines zu großen Primärschlüssels führt zu einem Fehler und Abbruch:
%Vor%Ich verstehe deine Frage nicht genau, aber wenn dein Ziel nur darin besteht, die Einfügung zu machen und ein gültiges Feld (zB eine ID) zu haben, dann füge die Werte ohne das ID-Feld ein, dafür steht "Standard" . Es wird funktionieren.
z. havin a id serial NOT NULL
und a CONSTRAINT table_pkey PRIMARY KEY(id)
in der Tabellendefinition werden die ID automatisch setzen und eine Sequenz table_id_seq
automatisch inkrementieren.
Tags und Links postgresql primary-key sequence