2008-09-11 15 views
20

gibt es eine Alternative für mysql_insert_id() PHP-Funktion für PostgreSQL? Die meisten Frameworks lösen das Problem teilweise, indem sie den aktuellen Wert der in der ID verwendeten Sequenz finden. Es gibt jedoch Zeiten, in denen der Primärschlüssel keine serielle Spalte ist.mysql_insert_id Alternative für Postgresql

Antwort

40

Vom PostgreSQL Sicht in Pseudo-Code:

* $insert_id = INSERT...RETURNING foo_id;-- only works for PostgreSQL >= 8.2. 

* INSERT...; $insert_id = SELECT lastval(); -- works for PostgreSQL >= 8.1 

* $insert_id = SELECT nextval('foo_seq'); INSERT INTO table (foo...) values ($insert_id...) for older PostgreSQL (and newer PostgreSQL) 

pg_last_oid() funktioniert nur dann, wenn Sie OIDs haben. OIDs sind seit PostgreSQL 8.1 standardmäßig deaktiviert.

Also, je nachdem, welche PostgreSQL-Version Sie haben, sollten Sie eine der oben genannten Methode wählen. Im Idealfall verwenden Sie natürlich eine Datenbankabstraktionsbibliothek, die das obige abstrahiert. Andernfalls wird im niedrigen Level-Code, es sieht aus wie:

Methode eins: INSERT ... RÜCKKEHR

// yes, we're not using pg_insert() 
$result = pg_query($db, "INSERT INTO foo (bar) VALUES (123) RETURNING foo_id"); 
$insert_row = pg_fetch_row($result); 
$insert_id = $insert_row[0]; 

Methode zwei: INSERT; lastval()

$result = pg_execute($db, "INSERT INTO foo (bar) values (123);"); 
$insert_query = pg_query("SELECT lastval();"); 
$insert_row = pg_fetch_row($insert_query); 
$insert_id = $insert_row[0]; 

Methode drei: nextval(); INSERT

$insert_query = pg_query($db, "SELECT nextval('foo_seq');"); 
$insert_row = pg_fetch_row($insert_query); 
$insert_id = $insert_row[0]; 
$result = pg_execute($db, "INSERT INTO foo (foo_id, bar) VALUES ($insert_id, 123);"); 

Die sicherste Wette wäre die dritte Methode sein, aber es ist unhandlich. Die sauberste ist die erste, aber Sie müssen eine aktuelle PostgreSQL ausführen. Die meisten DB-Abstraktions-Bibliotheken verwenden jedoch noch nicht die erste Methode.

+0

Große Antwort, ich wechselte aus Geschwindigkeitsgründen von der dritten Methode zur ersten. Ich benutze Python und psycopg2 und die Ausführung nur einer Anweisung für das Einfügen von Massendaten ist einfach ein schneller Weg. Möchten Sie wissen, ob die dritte wirklich sicherer ist als die erste? Ich würde denken, dass der erste und der dritte gleichermaßen sicher sind und der zweite eine Wettlaufbedingung hat. – Ross

3

Überprüfen Sie die RETURNING optional clause für eine INSERT-Anweisung. (Link zur offiziellen PostgreSQL-Dokumentation)

Aber im Grunde, was Sie tun:

INSERT INTO table (col1, col2) VALUES (1, 2) RETURNING pkey_col 

und die INSERT-Anweisung selbst liefert die ID (oder was auch immer Ausdruck, den Sie angeben) der betroffenen Zeile.

3

Von php.net:

$res=pg_query("SELECT nextval('foo_key_seq') as key"); 
$row=pg_fetch_array($res, 0); 
$key=$row['key']; 
// now we have the serial value in $key, let's do the insert 
pg_query("INSERT INTO foo (key, foo) VALUES ($key, 'blah blah')"); 

Diese immer eindeutigen Schlüssel bieten sollte, weil Schlüssel aus der Datenbank abgerufen werden nie wieder abgerufen werden.

3

Sie können auch verwenden:

$result = pg_query($db, "INSERT INTO foo (bar) VALUES (123) RETURNING foo_id"); 
$insert_row = pg_fetch_result($result, 0, 'foo_id'); 

Sie haben in pg_fetch_result die Nummer der Zeile und den Namen des Feldes angeben, die Sie suchen, ist dies eine genauere Möglichkeit, die Daten zu erhalten, die Sie brauchen, aber ich weiß nicht, ob dies eine Strafe in der Leistung der Abfrage hat. Denken Sie daran, dass diese Methode für PostgreSQL-Versionen ab Version 8.2 gilt.

+0

ja, es ist bereits in @ angch's Antwort erwähnt. Beachten Sie, dass dies jedoch nicht für andere SQL-Dialekte (sql-server, mysql usw.) verwendet werden kann – Jeffrey04