2008-09-11 9 views
20

Y at-il une alternative pour mysql_insert_id() fonction PHP pour PostgreSQL? La plupart des cadres résolvent partiellement le problème en trouvant la valeur actuelle de la séquence utilisée dans l'ID. Toutefois, il existe des fois que la clé primaire n'est pas une colonne série ....mysql_insert_id alternative pour postgresql

Répondre

40

Du point de vue PostgreSQL, en 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() ne fonctionne que lorsque vous avez OID. Les OID ont été désactivés par défaut depuis PostgreSQL 8.1. Donc, en fonction de la version de PostgreSQL que vous avez, vous devriez choisir l'une des méthodes ci-dessus. Idéalement, bien sûr, utilisez une bibliothèque d'abstraction de base de données qui résume ce qui précède. Sinon, dans le code de bas niveau, il ressemble à:

méthode: INSERT ... RETOURNER

// 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]; 

Méthode deux: 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]; 

Méthode trois: nextval(); INSÉRER

$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);"); 

Le pari le plus sûr serait la troisième méthode, mais c'est compliqué. Le plus propre est le premier, mais vous devez exécuter un PostgreSQL récent. La plupart des bibliothèques d'abstraction db n'utilisent pas encore la première méthode.

+0

Grande réponse, je suis passé de la troisième méthode à la première pour des raisons de vitesse. J'utilise python et psycopg2 et l'exécution d'une seule instruction pour l'insertion de données en masse est simplement un moyen plus rapide. Voudrais savoir si le troisième est vraiment plus sûr que le premier? Je pense que le premier et le troisième sont tout aussi sûrs et le second a une condition de concurrence. – Ross

3

Consultez la RETURNING optional clause pour une instruction INSERT. (Lien vers la documentation PostgreSQL officielle)

Mais au fond, vous faites:

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

et l'instruction INSERT lui-même renvoie l'identifiant (ou autre expression que vous spécifiez) de la ligne concernée.

3

De 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')"); 

Cela devrait toujours fournir clé unique, car la clé récupérée de la base de données ne sera jamais récupéré à nouveau.

3

Vous pouvez également utiliser:

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

Vous devez indiquer dans pg_fetch_result le numéro de la ligne et le nom du champ que vous recherchez, c'est une façon plus précise pour obtenir les données vous avez besoin, mais je ne sais pas si cela a une certaine pénalité dans l'exécution de la requête. Rappelez-vous que cette méthode est pour les versions 8.2 de PostgreSQL et plus.

+0

oui, il est déjà mentionné dans la réponse de @ angch. Notez que ceci n'est pas utilisable pour d'autres dialectes sql (sql-server, mysql, etc.) – Jeffrey04