views:

622

answers:

4

Hi All,

I am inserting a row with a char column for a hash based on (among other things) the row's auto id.

I know I can insert it, fetch the insert_id, calculate the hash, and update it.

Does anyone know of a way to do this in a single query? You would need the rows insert_id at the time of insert. Is that completely impossible, or is there something like current_insert_id()...

Thanks!

+7  A: 

No, there's no function in MySQL that gives you the current_insert_id().

The only way to get a generated ID value from an AUTO_INCREMENT field in MySQL is to do the INSERT and then call last_insert_id(). So your plan of doing a separate UPDATE to calculate the hash is probably what you'll have to do.

I can think of two other alternatives:

  • Generate the unique value yourself before the INSERT with some other mechanism besides the AUTO_INCREMENT. For example, see the UUID() function.

    SET @id = SELECT UUID();
    INSERT INTO MyTable (id, hash) VALUES (@id, hash(@id...));
    
  • Don't include the ID in your hash calculation.

Bill Karwin
+1  A: 

There's no way that I know of to do it in MySQL in one query, but you could do something like this in your server-side scripting language of choice:

<?php

$query = mysql_query("SHOW TABLE STATUS LIKE 'MyTable'");
$row = mysql_fetch_assoc($query);
$next_id = $row['Auto_increment'];

?>

...which gives you the id to incorporate in your SQL.

EDIT: I also found this answer which may be helpful.

da5id
This is susceptible to a race condition.
Bill Karwin
A: 

When I do inserts I do something like this:

INSERT INTO table (col1,col2) VALUES (data1,data2);SELECT LAST_INSERT_ID()

and just run the query like I was fetching data. In VB.NET the syntax is (assuming you have the MySql.Data.MySqlClient .dll):

Dim sql As String = "[sql string above]"
Dim dr As MySqlDataReader = YourRetrieveDataFunction(sql)

dr.Read()
yourObjectInstance.ID = dr(0)
dr.Close

It's technically two queries, but only one hit on the database :)

Jason
Eli wants the id that is *about* to be inserted, not the one that's just been inserted.
da5id
hmm... SELECT whatever, (SELECT id+1 FROM table ORDER BY id DESC LIMIT 1) AS newid .... ? i dunno if this actually works
Jason
ok i just tried it... subqueries to the rescue!
Jason
FWIW, querying the top id+1 is susceptible to a race condition. Don't use it if you have more than one concurrent client.
Bill Karwin
A: 

You can query the next-to-be-used value from the information_schema.TABLES table, the AUTO_INCREMENT column there. (You might be setting yourself up for a race condition?)

great_llama
Yes, this would be susceptible to a race condition.
Bill Karwin