optimized way to recover last mysql ID

Asked

Viewed 18,476 times

9

Which is the most optimized way to recover the last table id?

I tested these two methods and the orde by took a long time. There is some beyond these?

Note: nãp will be a query after Insert. It will be a separate query.

select max(campo_id) from tabela

select campo_id FROM tabela ORDER BY campo_id DESC LIMIT 1
  • 1

    None of these are for retrieving the last ID. These are for retrieving the Highest ID. Usually they match, but it is not an absolute truth.

2 answers

11


None of these alternatives serves to recover the last ID.

Your code is to recover the Highest ID. Usually the last and the largest coincide, but it is not an absolute truth.

To know the last ID inserted automatically, the code is this:

SELECT LAST_INSERT_ID;

Still remembering that you don’t even need the SELECT in most situations, if you are using a Mysql library in another language, or even the connector in C, it is common to have a specific function that already returns the value right after the INSERT.

But keep in mind that this only works if you made the last insertion on the same connection.

It’s not all flowers: if the last insert added 3 records in DB, this function returns the first of them, not the last.

As you said it is a separate query, what can help is this query that returns the next Automatic ID that will be used:

SELECT AUTO_INCREMENT
FROM   information_schema.tables
WHERE  table_name = 'nome da sua tabela'
AND    table_schema = 'nome do seu DB' ;


But then, what’s the problem with the question code?

If you really want to know the last entered, the only safe feature is to recover the data with LAST_INSERT_ID, or exaggerating, making a Trigger for this.

For example, see common situations where the question code will not return the last entered value:

  • If the last records are deleted, the LAST_INSERT_ID will still contain the entered value, but the question code will retrieve the ID previous to these (which will not match the next insertions).

  • If an insert is made by specifying a manually smaller ID than the entered one, there is no safe way to know which was the last one.


Now, you have to think of something important: Depending on the use you are going to make, you don’t really need the last inserted, but the largest existing. In this case, the question code solves.

Alternatively, you can use the technique of SELECT AUTOINCREMENT above, and subtract 1 to estimate what the previous one was. This also does not guarantee which actually was the last inserted but is less likely to give side effects.

Another care to take: may well happen to occur some other transaction in DB, and this value change before you use, so anything that escapes from the LAST_INSERT_ID can generate a race condition. The ideal is not to use the value for anything other than actually referencing the last line inserted.

Another warning: (to further complicate life) you should only use the LAST_INSERT_ID if the last insertion was not an error, otherwise you may be picking up a previous insertion ID. There are people who forehead turned to zero to know if you returned an ID or not, but this unreliable if it does not check whether the INSERT really succeeded.

As for the performance, the only way to be sure is by doing benchmarks, because it depends on a number of factors.

  • Thank you @Bacco

  • @Thallesdaniel gave a generic answer, but if you explain better what you will use the value for, or have any more questions, leave a comment that I can try to help.

  • at first is to generate a protocol before it even exists but I have a competition problem or attendant can generate at the same time I saw some methods to block the table but I did not believe that would be the best way

  • @Thallesdaniel if you need a protocol before having the data, has 2 most common paths: One is a separate table of protocols, in which you generate the protocol and then link to a larger record. Another way is to insert an incomplete form in the DB, and give an update during the service. Any of these alternatives will give you an ID. The idea of the protocol is precisely this, the simple fact that there is a service has to generate it, and store it, even if the service is discarded or incomplete. At least vc will have the protocol (ID), date and time of occurrence.

  • In fact, it’s even more accurate for diagnostics. Tomorrow or later you can do a search, and realize that Attendant X has 300 protocols, but only 100 calls, and that’s a sign that something’s wrong. And in this case, you will be using LAST_INSERT_ID as soon as you create the protocol, so it is perfectly safe and without competition problems, and you don’t need LOCK, transactions and other problematic things.

  • vlw even this path has cleared up a lot. For audit is much better msm

Show 1 more comment

0

Mysql is pretty easy. I was trying to do the same thing on SQL Server and it’s a sacrifice.

In Mysql you only need to use LAST_INSERT_ID().

Example: SELECT LAST_INSERT_ID() INTO @tabela

  • Yeah, very hard to use one SCOPE_IDENTITY(), CURRENT_IDENT('nome tabela')... Now tell me how you make one INSERT INTO tableA OUTPUT columns INTO @table SELECT * FROM tableB in Mysql?

  • Well, answer me first: what was the case where I needed the last ID inserted in an SQL Server 2012 table? Then what do you want to do with this mess of code?

  • The answer to the first question is Você não tem ideia, porque eu não disse.

  • At no time did I mention the MSSQL 2012, but you said: Eu estava tentando fazer a mesma coisa no SQL Server e é um sacrifício.... Just said that the @@IDENTITY (MSSQL 2000) has a similar behavior and we still have the SCOPE_IDENTITY() (MSSQL 2000) and the CURRENT_IDENT('table name') (MSSQL 2008) and the latter does what AP wanted to do on MySQL, however in MSSQL. And the command... It’s just something simple in the MSSQL which is a "sacrifice" in the MySQL, as well as Windows Functions and Common Table Express

Browser other questions tagged

You are not signed in. Login or sign up in order to post.