it-swarm.com.de

PostgreSQL nächster Wert der Sequenzen?

Ich verwende PostgreSQL für meine Codeigniter-Website. Ich benutze Grocery Crud zum Hinzufügen, Bearbeiten und Löschen von Operationen. Beim Bearbeiten oder Hinzufügen möchte ich eine hochgeladene Datei dynamisch umbenennen, basierend auf der ID des Inhalts. Ich bin dazu in der Lage, die callback_after_upload-Funktion von Grocery Crud zu verwenden. 

Ich möchte eine nächste ID des Inhalts, während Sie einen neuen Inhalt hinzufügen. Ich habe versucht, die Funktion nextval() zu verwenden, aber die Sequenz wird dadurch inkrementiert. Wie kann der letzte Wert der Sequenz ermittelt werden, ohne die Funktion nextval() zu verwenden?

Oder gibt es eine einfache Möglichkeit, dies zu tun?

27
i_nomad

RETURNING

In der heutigen PostgreSQL-Version 8.2 (8.2 oder höher) führen Sie dies mit einem einfachen Roundtrip zur Datenbank aus:

INSERT INTO tbl(filename)
VALUES ('my_filename')
RETURNING tbl_id;

tbl_id ist eine serial column. Mehr im Handbuch .

Wert explizit abrufen

Wenn filenametbl_id (redundant) einschließen muss, können Sie trotzdem eine einzelne Abfrage verwenden.
Verwenden Sie lastval() oder das spezifischere currval() :

INSERT INTO tbl (filename)
VALUES ('my_filename' || lastval())  -- or currval('tbl_tbl_id_seq')
RETURNING tbl_id;

Das Handbuch zu lastval():

Diese Funktion ist identisch mit currval, mit der Ausnahme, dass anstelle von Der Sequenzname als Argument ruft den Wert des letzten .__ ab. Sequenz, die von nextval in der aktuellen Sitzung verwendet wird.

Wenn Sie mehrere Sequenzen haben (oder haben können), die mit der Tabelle verknüpft sind (auch durch Auslöser oder andere Nebenwirkungen), können Sie mit surecurrval('tbl_tbl_id_seq') verwenden.

Name der Sequenz

Das string literal'tbl_tbl_id_seq' in meinem Beispiel soll der actual -Name der Sequenz sein und wird in regclass umgewandelt, was eine Ausnahme auslöst, wenn im aktuellen search_path keine Sequenz dieses Namens gefunden wird .

tbl_tbl_id_seq ist der automatisch generierte Standard für eine Tabelle tbl mit einer seriellen Spalte tbl_id. Es gibt jedoch keine Garantien. Eine Spaltenvorgabe kann Werte aus der Reihenfolge any abrufen, wenn sie definiert ist. Wenn beim Erstellen der Tabelle der Standardname verwendet wird, wählt Postgres den nächsten freien Namen gemäß einem hartcodierten Algorithmus.

Wenn Sie nicht den Namen der Sequenz für eine serial-Spalte kennen, suchen Sie sie mit der dedizierten Funktion pg_get_serial_sequence() nach. Kann auch on the fly gemacht werden:

INSERT INTO tbl (filename)
VALUES ('my_filename' || currval(pg_get_serial_sequence('tbl', 'tbl_id'))
RETURNING tbl_id;

SQL Geige.

34

Auf den zuvor erhaltenen Wert einer Sequenz wird mit der Funktion currval() zugegriffen. 

Dies gibt jedoch nur dann einen Wert zurück, wenn nextval()davor aufgerufen wurde. 

Es gibt absolut keine Möglichkeit, den nächsten Wert einer Sequenz zu "spähen", ohne ihn tatsächlich zu erhalten. 

Ihre Frage ist jedoch unklar. Wenn Sie nextval() aufrufen, bevor Sie die Einfügung ausführen, können Sie diesen Wert in der Einfügung verwenden. Oder noch besser, verwenden Sie currval() in Ihrer Einfügeanweisung:

select nextval('my_sequence') ...

... do some stuff with the obtained value

insert into my_table(id, filename)
values (currval('my_sequence'), 'some_valid_filename');
15

Auch wenn dies irgendwie möglich ist, ist dies eine schreckliche Idee, da es möglich wäre, eine Sequenz zu erhalten, die dann von einer anderen Platte verwendet wird!

Eine viel bessere Idee ist, den Datensatz zu speichern und anschließend die Sequenz abzurufen.

0
Brian

Wenn Sie nicht in einer Sitzung sind, können Sie nur nextval ('you_sequence_name') verwenden und es ist in Ordnung.

0
Irlan Cidade

Ich habe es versucht und es funktioniert perfekt 

@Entity
public class Shipwreck {
  @Id
  @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq")
  @Basic(optional = false)
  @SequenceGenerator(name = "seq", sequenceName = "shipwreck_seq", allocationSize = 1)
  Long id;

....

CREATE SEQUENCE public.shipwreck_seq
    INCREMENT 1
    START 110
    MINVALUE 1
    MAXVALUE 9223372036854775807
    CACHE 1;
0
user2699843

Um Ihre Frage wörtlich zu beantworten, erfahren Sie, wie Sie den nächsten Wert einer Sequenz erhalten, ohne ihn zu erhöhen:

SELECT
 CASE WHEN is_called THEN
   last_value + 1
 ELSE
   last_value
 END
FROM sequence_name

Es ist offensichtlich keine gute Idee, diesen Code in der Praxis zu verwenden. Es gibt keine Garantie, dass die nächste Zeile wirklich diese ID hat. Für Debugging-Zwecke kann es jedoch interessant sein, den Wert einer Sequenz zu kennen, ohne sie inkrementieren zu müssen. Auf diese Weise können Sie dies tun.

0
Jakob Egger