2008-09-11 13 views
20

czy istnieje alternatywa dla funkcji php dla PostgreSQL dla mysql_insert_id()? Większość frameworków rozwiązuje problem częściowo poprzez znalezienie bieżącej wartości sekwencji użytej w identyfikatorze. Jednak są chwile, że klucz podstawowy nie jest kolumną szeregową ...mysql_insert_id alternatywa dla postgresql

Odpowiedz

40

Z punktu widzenia PostgreSQL, w pseudo-kodzie:

* $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() działa tylko wtedy, gdy masz OID. OID zostały domyślnie wyłączone od czasu PostgreSQL 8.1.

W zależności od wersji PostgreSQL należy wybrać jedną z powyższych metod. Idealnie byłoby oczywiście użyć biblioteki abstrakcji baz danych, która usuwa powyższe. W przeciwnym razie, w niskim poziomie kodu, wygląda na to:

Metoda pierwsza: INSERT ... POWRÓT

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

Sposób drugi: 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]; 

Metoda trzecia: nextval(); WSTAW

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

Najbezpieczniejszy zakład byłby trzecią metodą, ale jest nieporęczny. Najczystsze jest pierwszym, ale musisz uruchomić najnowszy PostgreSQL. Większość bibliotek db abstrakcji nie używa jeszcze pierwszej metody.

+0

Świetna odpowiedź, przeszedłem od trzeciej metody do pierwszej ze względu na prędkość. Używam Pythona i psycopg2 i wykonanie tylko jednej instrukcji do wstawiania danych luzem jest po prostu szybszym sposobem. Chciałbyś wiedzieć, czy trzeci jest naprawdę bezpieczniejszy od pierwszego? Sądzę, że pierwszy i trzeci są równie bezpieczne, a drugi ma stan wyścigu. – Ross

3

Zapoznaj się z RETURNING optional clause dla instrukcji INSERT. (Link do oficjalnej dokumentacji PostgreSQL)

Ale w zasadzie, to zrobić:

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

a sam INSERT zwraca identyfikator (lub cokolwiek wyrażenie okreslic) rozpatrywanego rzędu.

3

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

Powinno to zawsze zapewniają unikalny klucz, bo klucz pobierane z bazy danych zostaną nigdy odzyskać.

3

Można również użyć:

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

Trzeba określić w pg_fetch_result numer wiersza i nazwę pola, które szukasz, jest to bardziej precyzyjny sposób, aby uzyskać dane potrzebujesz, ale nie wiem, czy ma to pewien wpływ na wydajność zapytania. Pamiętaj, że ta metoda jest dla wersji PostgreSQL 8.2 i nowszych.

+0

tak, jest już wspomniane w odpowiedzi @ angcha. Zauważ, że nie jest to jednak możliwe w przypadku innych dialektów języka SQL (sql-server, mysql itp.) – Jeffrey04