$stmt2 = $db->prepare("INSERT INTO
usertabbrige(`tabId`,`uId`)
VALUES
((LAST_INSERT_ID()),$userId)");
anything wrong with this query? It's wrap within my first stmt, which will insert a value into uId (PK) in other table. usertabbrige table contain a field uId which is a FK.
Do not use LAST_INSERT_ID() in your query. You dont know which insert statement was last in current session. You can insert to one table, and if you use LAST_INSERT_ID() in another query, you dont actually know where LAST_INSERT_ID() came from.
As I can see you are using PDO. After you executed an insert query, save id:
$db->query("INSERT INTO ...");
$lastInsertedTabId = $db->lastInsertId;
Use it in your next prepared statement
$stmt2 = $db->prepare("INSERT INTO
usertabbrige(`tabId`,`uId`)
VALUES
($lastInsertedTabId ,$userId)");
Related
I am having an issue using Last_Insert_Id in a VB.NET TableAdapter Insert query wired to a MySQL database. I've read through numerous posts on this site and others regarding Last_Insert_ID and Scope_Identity, etc. None of which have worked in my case.
A little background, I have two tables, one holds login information (Auto-generated ID, username, password). Another table has a foreign key relationship on the ID values and contains ID, first name, last name, city, state.
In my TableAdapter I have an Insert query that inserts values into the first table and is supposed to return the ID value so that an Insert can be done on table 2.
Here is my Query:
INSERT INTO user_logins (user_login, user_pass)
VALUES (#p1, #p2)
I wanted to add Last_Insert_Id to make the query
INSERT INTO user_logins (user_login, user_pass)
VALUES (#p1, #p2)
SELECT LAST_INSERT_ID();
However that will only return a value of 1, regardless of what the ID is. If I open the Query Builder I get a message that states "Unable to parse query text". I tried changing the ExecuteMode to Scalar, but that didn't help either.
The Insert part is working perfectly, if I could only obtain the ID value back after insert.
Does anyone know anything I might try, or alternatively, some better way to achieve this?
Thanks!
You don't even need to use SELECT LAST_INSERT_ID();
just INSERT INTO user_logins (user_login, user_pass) VALUES (#p1, #p2) is OK
To retrieve last insert Id you can use two ways
Dim t As Integer
cmd.ExecuteNonQuery()
t = (Int32) cmd.LastInsertedId
OR
t = Convert.ToInt32(cmd.ExecuteScalar())
I'm need to get the ID of the last record inserted into my table.
INSERT INTO mytable (Column1, Column2) VALUE ('Test', 'Bob');
SELECT/SET LAST_INSERT_ID() as NewID;
Response.Write rst("NewID") '(for example)
Can it run in one statement, or do I need to run the SELECT LAST_INSERT_ID after the INSERT SQL has ran.
I am using MYSQL and ASP
You need to run it after every statment as it will always returns one id of most recent inserted record.
To achieve your goal,
You need to do is, whenever any record inserted to table, get the last id and store it in to any string/table every time and return it from your sproc. This way you get all inserted id at once.
I think that you need to run 2 procedure, first insert and then select order by id desc
I am currently using MySQL. I have a table that has an auto_increment 'id' field, and an 'imgname' field containing a string that is the file name of an image.
I need to generate the 'imgname' value using the auto_increment value that is create by an INSERT INTO statement. The problem is, I don't know this value until I can use mysql_insert_id, AFTER the insert query has run. I would like to know if it's possible to access this value DURING the insert query somehow and then use it to generate my string in the query statement.
Thanks in advance.
I would keep the id and imgname independent of each other and combine the two on SELECT when needed. If the need is frequent enough, create a view.
Have a look at LAST_INSERT_ID() function. If performance is not an issue, INSERT regularly, and then UPDATE using LAST_INSERT_ID(), like:
UPDATE table SET name = CONCAT(name, "-", LAST_INSERT_ID()) WHERE id = LAST_INSERT_ID();
If I insert multiple records with a loop that executes a single record insert, the last insert id returned is, as expected, the last one. But if I do a multiple records insert statement:
INSERT INTO people (name,age)
VALUES ('William',25), ('Bart',15), ('Mary',12);
Let's say the three above are the first records inserted in the table. After the insert statement I expected the last insert id to return 3, but it returned 1. The first insert id for the statement in question.
So can someone please confirm if this is the normal behavior of LAST_INSERT_ID() in the context of multiple records INSERT statements. So I can base my code on it.
Yes. This behavior of last_insert_id() is documented in the MySQL docs:
Important
If you insert multiple rows using a single INSERT statement, LAST_INSERT_ID() returns the value generated for the first inserted row only. The reason for this is to make it possible to reproduce easily the same INSERT statement against some other server.
This behavior is mentioned on the man page for MySQL. It's in the comments but is not challenged, so I'm guessing it's the expected behavior.
I think it's possible if your table has unique autoincrement column (ID) and you don't require them to be returned by mysql itself. I would cost you 3 more DB requests and some processing. It would require these steps:
Get "Before MAX(ID)" right before your insert:
SELECT MAX(id) AS before_max_id FROM table_name`
Make multiple INSERT ... VALUES () query with your data and keep them:
INSERT INTO table_name
(col1, col2)
VALUES
("value1-1" , "value1-2"),
("value2-1" , "value2-2"),
("value3-1" , "value3-2"),
ON DUPLICATE KEY UPDATE
Get "After MAX(ID)" right after your insert:
SELECT MAX(id) AS after_max_id FROM table_name`
Get records with IDs between "Before MAX(ID)" and "After MAX(ID)" including:
SELECT * FROM table_name WHERE id>$before_max_id AND id<=$after_max_id`
Do a check of retrieved data with data you inserted to match them and remove any records that were not inserted by you. The remaining records have your IDs:
foreach ($after_collection as $after_item) {
foreach ($input_collection as $input_item) {
if ( $after_item->compare_content($input_item) ) {
$intersection_array[] = $after_item;
}
}
}
This is just how a common person would solve it in a real world, with parts of code. Thanks to autoincrement it should get smallest possible amount of records to check against, so they will not take lot of processing. This is not the final "copy & paste" code - eg. you have to create your own function compare_content() according you your needs.
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!
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.
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.
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?)
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 :)