it-swarm.com.de

PostgreSQL-Funktion für die zuletzt eingefügte ID

Wie bekomme ich in PostgreSQL die letzte ID in eine Tabelle?

In MS SQL gibt es SCOPE_IDENTITY ().

Bitte raten Sie mir nicht, so etwas zu verwenden:

select max(id) from table
260
Anton

(tl;dr: gehe zu Option 3: EINFÜGEN mit RETURNING)

Es sei daran erinnert, dass es in postgresql kein "id" -Konzept für Tabellen gibt, nur sequence (die normalerweise, aber nicht notwendigerweise als Standardwerte für Ersatzschlüsselschlüssel verwendet werden, mit dem Pseudotyp SERIAL ). 

Wenn Sie die ID einer neu eingefügten Zeile erhalten möchten, gibt es mehrere Möglichkeiten:


Option 1: CURRVAL(<sequence name>);

Zum Beispiel:

  INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John');
  SELECT currval('persons_id_seq');

Der Name der Sequenz muss bekannt sein, er ist wirklich willkürlich. In diesem Beispiel gehen wir davon aus, dass die Tabelle persons eine mit dem Pseudotyp id erstellte SERIAL-Spalte hat. Um sich nicht darauf zu verlassen und sich sauberer zu fühlen, können Sie stattdessen pg_get_serial_sequence verwenden:

  INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John');
  SELECT currval(pg_get_serial_sequence('persons','id'));

Einschränkung: currval() funktioniert nur nach einer INSERT (die nextval() ausgeführt hat) in derselben Sitzung.


Option 2: LASTVAL();

Dies ist ähnlich wie beim vorherigen, nur dass Sie den Sequenznamen nicht angeben müssen: Er sucht nach der zuletzt geänderten Sequenz (immer innerhalb Ihrer Sitzung, gleiche Einschränkung wie oben).


Sowohl CURRVAL als auch LASTVAL sind gleichzeitig sicher. Das Verhalten von Sequence in PG ist so ausgelegt, dass unterschiedliche Sitzungen nicht stören. Es besteht also keine Gefahr von Race-Bedingungen (wenn eine andere Session eine andere Zeile zwischen INSERT und SELECT einfügt, bekomme ich immer noch meinen korrekten Wert).

Sie haben jedoch ein subtiles potentielles Problem. Wenn die Datenbank über TRIGGER (oder RULE) verfügt, die beim Einfügen in die Tabelle persons einige zusätzliche Einfügungen in andere Tabellen vornimmt, dann liefert LASTVAL wahrscheinlich den falschen Wert. Das Problem kann sogar bei CURRVAL auftreten, wenn die zusätzlichen Einfügungen in dieselbe persons-Tabelle vorgenommen werden (dies ist viel weniger üblich, aber das Risiko besteht immer noch).


Option 3: INSERT mit RETURNING 

INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John') RETURNING id;

Dies ist der sauberste, effizienteste und sicherste Weg, um die ID zu erhalten. Es hat keine der Risiken des vorherigen. 

Nachteile? Fast keine: Möglicherweise müssen Sie die Art und Weise ändern, wie Sie Ihre INSERT-Anweisung aufrufen (im schlimmsten Fall erwartet Ihre API- oder DB-Schicht nicht, dass ein INSERT einen Wert zurückgibt). es ist nicht Standard-SQL (wen interessiert); es ist verfügbar seit Postgresql 8.2 (Dez 2006 ...)


Fazit: Wenn möglich, wählen Sie Option 3. Woanders bevorzugen Sie 1.

Hinweis: Alle diese Methoden sind unbrauchbar, wenn Sie die zuletzt global eingefügte ID erhalten möchten (nicht unbedingt in Ihrer Sitzung). Dazu müssen Sie auf select max(id) from table zurückgreifen (dabei werden nicht festgeschriebene Einfügungen nicht aus anderen Transaktionen gelesen).

494
leonbloy

Siehe die Klausel RETURNING der Anweisung INSERT . Grundsätzlich dient das INSERT als Abfrage und gibt den Wert zurück, der eingefügt wurde. 

70
kwatford

sie können die RETURNING-Klausel in der INSERT-Anweisung genauso wie im Folgenden verwenden

wgzhao=# create table foo(id int,name text);
CREATE TABLE
wgzhao=# insert into foo values(1,'wgzhao') returning id;
 id 
----
  1
(1 row)

INSERT 0 1
wgzhao=# insert into foo values(3,'wgzhao') returning id;
 id 
----
  3
(1 row)

INSERT 0 1

wgzhao=# create table bar(id serial,name text);
CREATE TABLE
wgzhao=# insert into bar(name) values('wgzhao') returning id;
 id 
----
  1
(1 row)

INSERT 0 1
wgzhao=# insert into bar(name) values('wgzhao') returning id;
 id 
----
  2
(1 row)

INSERT 0 
28
wgzhao

Leonbloys Antwort ist ziemlich vollständig. Ich würde nur den Sonderfall hinzufügen, in dem der letzte eingefügte Wert aus einer PL/pgSQL-Funktion herausgefunden werden muss, wobei OPTION 3 nicht genau passt.

Zum Beispiel, wenn wir die folgenden Tabellen haben:

CREATE TABLE person(
   id serial,
   lastname character varying (50),
   firstname character varying (50),
   CONSTRAINT person_pk PRIMARY KEY (id)
);

CREATE TABLE client (
    id integer,
   CONSTRAINT client_pk PRIMARY KEY (id),
   CONSTRAINT fk_client_person FOREIGN KEY (id)
       REFERENCES person (id) MATCH SIMPLE
);

Wenn wir einen Kundendatensatz einfügen müssen, müssen wir auf einen Personendatensatz verweisen. Angenommen, wir möchten eine PL/pgSQL-Funktion entwickeln, die einen neuen Datensatz in den Client einfügt, sich aber auch um den neuen Personendatensatz kümmert. Dazu müssen wir eine leichte Variante der Option 3 von leonbloy verwenden:

INSERT INTO person(lastname, firstname) 
VALUES (lastn, firstn) 
RETURNING id INTO [new_variable];

Beachten Sie, dass es zwei INTO-Klauseln gibt. Daher wäre die PL/pgSQL-Funktion wie folgt definiert:

CREATE OR REPLACE FUNCTION new_client(lastn character varying, firstn character varying)
  RETURNS integer AS
$BODY$
DECLARE
   v_id integer;
BEGIN
   -- Inserts the new person record and retrieves the last inserted id
   INSERT INTO person(lastname, firstname)
   VALUES (lastn, firstn)
   RETURNING id INTO v_id;

   -- Inserts the new client and references the inserted person
   INSERT INTO client(id) VALUES (v_id);

   -- Return the new id so we can use it in a select clause or return the new id into the user application
    RETURN v_id;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE;

Jetzt können wir die neuen Daten einfügen mit: 

SELECT new_client('Smith', 'John');

oder 

SELECT * FROM new_client('Smith', 'John');

Und wir bekommen die neu erstellte ID.

new_client
integer
----------
         1
17
Krauss

Siehe das Beispiel unten

CREATE TABLE users (
    -- make the "id" column a primary key; this also creates
    -- a UNIQUE constraint and a b+-tree index on the column
    id    SERIAL PRIMARY KEY,
    name  TEXT,
    age   INT4
);

INSERT INTO users (name, age) VALUES ('Mozart', 20);

Um die letzte eingefügte ID zu erhalten, verwenden Sie diese für die Tabelle "Benutzer".

SELECT currval(pg_get_serial_sequence('users', 'id'));
8
RINSON KE
SELECT CURRVAL(pg_get_serial_sequence('my_tbl_name','id_col_name'))

Sie müssen natürlich den Tabellennamen und den Spaltennamen angeben.

Dies wird für die aktuelle Sitzung/Verbindung sein http://www.postgresql.org/docs/8.3/static/functions-sequence.html

7
jishi

Für diejenigen, die den gesamten Datensatz abrufen müssen, können Sie hinzufügen

returning *

bis zum Ende Ihrer Abfrage, um das all-Objekt einschließlich der ID abzurufen.

3
emreoktem

Versuche dies:

select nextval('my_seq_name');  // Returns next value

Wenn dies 1 zurückgibt (oder was auch immer der start_value für Ihre Sequenz ist), setzen Sie die Sequenz auf den ursprünglichen Wert zurück und übergeben Sie das Flag false:

select setval('my_seq_name', 1, false);

Andernfalls, 

select setval('my_seq_name', nextValue - 1, true);

Dadurch wird der Sequenzwert auf den ursprünglichen Zustand zurückgesetzt und "setval" gibt den Sequenzwert zurück, nach dem Sie suchen.

1
Oozman

Postgres hat einen eingebauten Mechanismus für dasselbe, der in derselben Abfrage die ID zurückgibt oder was auch immer die Abfrage zurückgeben soll. Hier ist ein Beispiel. Stellen Sie sich vor, Sie haben eine Tabelle mit 2 Spalten column1 und column2 erstellt und möchten, dass column1 nach jeder Einfügung zurückgegeben wird.

# create table users_table(id serial not null primary key, name character varying);
CREATE TABLE
#insert into users_table(name) VALUES ('Jon Snow') RETURNING id;
 id 
----
  1
(1 row)

# insert into users_table(name) VALUES ('Arya Stark') RETURNING id;
 id 
----
  2
(1 row)
0
Sandip Debnath