2008-09-11 38 views
20

¿hay una alternativa para la función php mysql_insert_id() para PostgreSQL? La mayoría de los marcos están resolviendo el problema parcialmente al encontrar el valor actual de la secuencia utilizada en el ID. Sin embargo, hay ocasiones en que la clave principal no es una columna en serie ....mysql_insert_id alternativa para postgresql

Respuesta

40

Desde el punto de vista de PostgreSQL, en pseudo-código:

* $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() sólo funciona cuando usted tiene OID. Los OID han estado desactivados por defecto desde PostgreSQL 8.1.

Por lo tanto, dependiendo de la versión de PostgreSQL que tenga, debe elegir uno de los métodos anteriores. Idealmente, por supuesto, use una biblioteca de abstracción de base de datos que abstraiga lo anterior. De lo contrario, en el código de bajo nivel, que parece:

Método uno: INSERT ... Volviendo

// 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étodo dos: 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étodo three: nextval(); INSERTAR

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

La apuesta más segura sería el tercer método, pero es difícil de manejar. El más limpio es el primero, pero necesitarías ejecutar un PostgreSQL reciente. La mayoría de las bibliotecas de abstracción de db todavía no usan el primer método.

+0

Gran respuesta, pasé del tercer método al primero por razones de velocidad. Estoy usando python y psycopg2 y la ejecución de una sola declaración para la inserción masiva de datos es simplemente una forma más rápida. Me gustaría saber si el tercero es realmente más seguro que el primero. Creo que el primero y el tercero son igualmente seguros y el segundo tiene una condición de carrera. – Ross

3

Consulte la RETURNING optional clause para obtener una instrucción INSERT. (Enlace a la documentación oficial de PostgreSQL)

Pero básicamente, lo hace:

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

y la instrucción INSERT en sí devuelve el ID (o lo que sea expresión especifica) de la fila afectada.

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

Esto siempre debe proporcionar clave única, dado que esta clave recuperada de la base de datos será nunca se recuperó de nuevo.

3

También puede utilizar:

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

Se tiene que especificar en pg_fetch_result el número de la fila y el nombre del campo que se está buscando, esta es una manera más precisa para obtener los datos que lo necesita, pero no sé si esto tiene alguna penalización en el desempeño de la consulta. Recuerde que este método es para las versiones 8.2 y superiores de PostgreSQL.

+0

sí, ya se menciona en la respuesta de @ angch. Tenga en cuenta que esto no es utilizable para otros sql-dialect (sql-server, mysql etc.) aunque – Jeffrey04