2011-12-01 6 views
10

stavo rivedendo un modulo Drupal quando ho trovato questo modello per ottenere l'id della riga dell'ultimo inserita:È concettualmente giusto fare un SELECT MAX (id) ecc. Per trovare l'ultima riga inserita?

SELECT MAX(id) FROM ... WHERE ... 

in cui l'ID è un campo di lavoro in un modo consueto autoincrement.

È concettualmente giusto fare questo? C'è qualche situazione in cui questo modello fallirà in un ambiente MySQL/PostgreSQL?

Edit:

Grazie per gli ottimi commenti e le risposte!

vorrei chiarire la mia domanda: volevo dire una situazione in cui qualcuno vorrebbe scoprire l'id dell'ultima riga inserita indipendentemente dalla sessione di.

+1

Non sono sicuro sul concettualmente giusto, ma penserei che se il seme per quella colonna fosse mai cambiato potrebbe non essere il valore corretto. – user1231231412

+4

Vedere [Qual è il modo stardard di ottenere l'ultimo ID di inserimento?] (Http://stackoverflow.com/questions/5048602/whats-the-stardard-way-of-getting-the-last-insert-id) –

+0

Do intendi l'ultimo record inserito dalla sessione corrente? O solo un generico "qual è il record più recente in questa tabella"? Molte risposte qui sembrano assumere il primo, e se questo è il caso, hanno ragione. Se il processo alla ricerca di un massimo (id) non sta cercando un record inserito da quel processo, non posso pensare a uno scenario in cui max (id) non darà "il record più recente nella tabella". – MatBailie

risposta

12

Questo sembra soggettivo, ma direi di no, che non è concettualmente giusto, perché:

  • si desidera che la più recente inserito fila
  • ma la query guarda al massimo valore di id

Sì, c'è qualche rela tra ID max e inserimento più recente, ma considerare quanto segue:

  • e se la riga inserita più di recente è stata eliminata?

Risposta su MySQL: si ottengono risultati diversi. Nota che non c'è nemmeno bisogno di essere multithreading o più processi perché questo fallisca. Questo perché sono due cose diverse (che, in genere, possono spesso produrre gli stessi risultati).

select max(id) from <tablename> 

vs

select last_insert_id() 

(indovinare quale si adatta.)


@Dems indicate che il PO è ambigua.Io chiarire il mio punto principale:

Stiamo parlando di tre diversi tipi di informazioni:

  • massima id valore
  • id di fila più recentemente inserita, specifici per una sessione
  • id della riga inserita di recente nella tabella (indipendentemente dalla sessione)

La cosa pericolosa è che a volte, l'interrogazione di uno darà la risposta giusta per un altro - ma non sempre.

+2

È importante sapere se l'OP indica di trovare l'ultimo record inserito "da questa sessione" o solo il record più recente nella tabella. È una domanda fondamentalmente diversa, e non ho idea di cosa stia chiedendo l'OP. – MatBailie

0

PostgreSQL si hanno a che fare con sequences quindi tutto dipende come la sua configurato

+1

DB2 ha anche 'sequenze', che possono contare all'indietro! –

2

In MySQL si può semplicemente utilizzare LAST_INSERT_ID() che è più garantito il funzionamento.

+3

'last_insert_id()' funziona solo nella sessione corrente supponendo che tu abbia aggiunto il valore di auto-incremento, un altro client non vedrà il tuo nuovo valore di last_insert_id() – triclosan

0

Senza conoscere le specifiche della vostra situazione particolare, direi che questo non è un modo sicuro. Pensa a una situazione in cui hai più clienti che inseriscono i record tutto il tempo. Puoi metterti in una condizione di gara con conseguenze molto brutte. Puoi provare a creare un blocco, ma questo potrebbe finire per introdurre un cattivo collo di bottiglia.

+0

Dipende da ciò per cui viene utilizzato. Ma non ho potuto elaborare una condizione di gara che * contenga *. Il processo A inizia inserendo 100 record, il processo B inizia inserendo 1 record, il processo B è bloccato da A, il record avrà sempre un ID più alto. In realtà non riesco a creare uno scenario nella mia testa che potrebbe portare a un record precedente che appare dopo un record successivo quando ordinato da una colonna di identità. – MatBailie

1

Dipende dalla clausola WHERE e da come l'applicazione si inserisce in quella tabella. SELECT max(ID) FROM table restituirà sempre l'ID più grande al momento dell'esecuzione della query. Supponendo che l'ID sia un auto_increment della chiave primaria, restituirà la riga più recente. Tuttavia, in ambienti multi-threaded come i server web, potrebbe non essere l'ID che ci si aspetta poiché un altro processo potrebbe averlo inserito anche in quella tabella. Ad esempio, se il codice PHP viene inserito nella tabella, allora select max(id) si aspetta di ottenere quella riga appena inserita, potrebbe non funzionare perché un altro processo potrebbe aver inserito un'altra riga dopo aver fatto l'inserimento e prima di fare il tuo select max.

Se l'ID è una chiave primaria auto_increment (mysql) allora MySql's last_insert_id() o PHP mysql_insert_id() è in genere una scelta migliore. Ma ancora, senza conoscere la tabella, la clausola WHERE, o cosa Drupal si aspetta da questa query, non è possibile dire se Drupal stia "facendo qualcosa di sbagliato".

5

selezionare max (id) sarebbe garantito solo per recuperare il record con l'ID più alto. potrebbe non essere necessariamente l'ULTIMO record inserito nella tabella. Ricorda che le operazioni DB possono essere eseguite in parallelo. È possibile inserire un record e ottenere l'ID # 5. Ma quando arrivi a fare il select MAX(id), qualcun altro potrebbe aver inserito un altro record e ora il massimo è davvero # 6.

Inoltre, non è possibile utilizzarlo per prevedere quale potrebbe essere il prossimo ID assegnato. Considera il caso in cui alcuni inserimenti sono fatti in una transazione. L'ultimo record impegnato nel DB è nuovamente # 5, quindi vengono eseguiti 3 inserimenti (# 6, # 7, # 8), quindi vengono ripristinati. Il prossimo inserimento da eseguire sarà in realtà # 9, non ancora # 6 - mysql non ricicla i numeri ID dalle transazioni fallite. E non c'è alcuna garanzia che TU otterresti # 9 - qualche altra sessione potrebbe fare l'inserto prima di arrivare ad esso, quindi il tuo quarto inserimento potrebbe essere # 10 o # 10.000.000.

1

Leggi questo: Directive 595

Epic fail fidarsi MAX (id), non riesce alla grande.

Problemi correlati