In Mysql I am inserting a row with Insert command in a table of mysql , now I want the Id of last row Inserted , I am using
SELECT LAST_INSERT_ID() ;
But it gives me 0 as output every time .
Please help me in this.
LAST_INSERT_ID() only returns values that have been auto-generated by the MySQL server for an AUTO_INCREMENT column; when you insert a specific value, no auto-generation takes place and no value will be returned by LAST_INSERT_ID().
You could assign a value to LAST_INSERT_ID yourself:
INSERT INTO table (uuid) VALUES (LAST_INSERT_ID(12345));
LAST_INSERT_ID(value) assigns value to be returned by subsequent calls to LAST_INSERT_ID(), and returns that same value. Unfortunately, this only works for integer values, and will not be useful with UUIDs.
Why would you want to select something that is not autogenerated by insert, but passed to it? The reason is that you are using UUID() in the insert statement. I'd suggest you first to select the UUID, and then pass it to the insert
SELECT #id := UUID();
INSERT INTO tablename(id, value) VALUES(#id, somevalue)
you are assigning autoincrement an uuid this is what you are doing wrong
autoincrement field will be inserted automatically
other than that you will be getting 0 result in LAST_INSERT_ID()
First you have to use one auto incremented line.
if you are using php then use this method :
$foo = mysql_insert_id();
take a look http://php.net/manual/en/function.mysql-insert-id.php
in c# i use like this:
connection.Open();
cmd = new MySql.Data.MySqlClient.MySqlCommand();
cmd.Connection = connection;
cmd.CommandText = "INSERT INTO o_test(game_id, user_id, date) values(?game_id, ?uid, ?date)";
cmd.Prepare();
cmd.Parameters.AddWithValue("?game_id", null);
cmd.Parameters.AddWithValue("?uid", words[1]);
cmd.Parameters.AddWithValue("?date", words[2]);
cmd.ExecuteNonQuery();
int game_id;
cmd.Parameters.Add(new MySqlParameter("newId", cmd.LastInsertedId));
game_id = Convert.ToInt32(cmd.Parameters["#newId"].Value);
If you want to select all columns from the last inserted id, you can go that way:
SELECT * FROM table WHERE id = (SELECT MAX(id) FROM table)
Related
Normally I can insert a row into a MySQL table and get the last_insert_id back. Now, though, I want to bulk insert many rows into the table and get back an array of IDs. Does anyone know how I can do this?
There are some similar questions, but they are not exactly the same. I don't want to insert the new ID to any temporary table; I just want to get back the array of IDs.
Can I retrieve the lastInsertId from a bulk insert?
Mysql mulitple row insert-select statement with last_insert_id()
Old thread but just looked into this, so here goes: if you are using InnoDB on a recent version of MySQL, you can get the list of IDs using LAST_INSERT_ID() and ROW_COUNT().
InnoDB guarantees sequential numbers for AUTO INCREMENT when doing bulk inserts, provided innodb_autoinc_lock_mode is set to 0 (traditional) or 1 (consecutive).
Consequently you can get the first ID from LAST_INSERT_ID() and the last by adding ROW_COUNT()-1.
The only way I can think it could be done is if you store a unique identifier for each set of rows inserted (guid)
then select the row ids.
e.g:
INSERT INTO t1
(SELECT col1,col2,col3,'3aee88e2-a981-1027-a396-84f02afe7c70' FROM a_very_large_table);
COMMIT;
SELECT id FROM t1
WHERE guid='3aee88e2-a981-1027-a396-84f02afe7c70';
You could also generate the guid in the database by using uuid()
Lets assume we have a table called temptable with two cols uid, col1 where uid is an auto increment field. Doing something like below will return all the inserted id's in the resultset. You can loop through the resultset and get your id's. I realize that this is an old post and this solution might not work for every case. But for others it might and that's why I'm replying to it.
# lock the table
lock tables temptable write;
#bulk insert the rows;
insert into temptable(col1) values(1),(2),(3),(4);
#get the value of first inserted row. when bulk inserting last_insert_id() #should give the value of first inserted row from bulk op.
set #first_id = last_insert_id();
#now select the auto increment field whose value is greater than equal to #the first row. Remember since you have write lock on that table other #sessions can't write to it. This resultset should have all the inserted #id's
select uid from temptable where uid >=#first_id;
#now that you are done don't forget to unlock the table.
unlock tables;
It's worth noting that #Dag Sondre Hansen's answer can also be implemented in case you have innodb_autoinc_lock_mode set to 2 by simply locking the table before insert.
LOCK TABLE my_table WRITE;
INSERT INTO my_table (col_a, col_b, col_c) VALUES (1,2,3), (4,5,6), (7,8,9);
SET #row_count = ROW_COUNT();
SET #last_insert_id = LAST_INSERT_ID();
UNLOCK TABLES;
SELECT id FROM my_table WHERE id >= #last_insert_id AND id <= #last_insert_id + (#row_count - 1);
Here's a fiddle demonstrating: https://www.db-fiddle.com/f/ahXAhosYkkRmwqR9Y4mAsr/0
I wouldn't be sure that auto increment value will increase item by 1. and there will be huge problems if your DB will have Master // Master replication and to resolve auto_increment duplicate exclusion. AI will be +2 instead of +1, also if there will be one more master it will come to +3. so relay on thing like AUTO_INCREMENT is going up for 1 is killing your project.
I see only some good options to do that.
this SQL snippet will have no problems with multiple masters and give good results until you will need only inserted records. on multiple requests without transactions can catch other inserts records.
START TRANSACTION;
SELECT max(id) into #maxLastId FROM `main_table`;
INSERT INTO `main_table` (`value`) VALUES ('first'), ('second') ON DUPLICATE KEY UPDATE `value` = VALUES(`value`);
SELECT `id` FROM `main_table` WHERE id > #maxLastId OR #maxLastId IS NULL;
COMMIT;
(if you will need also updated records by DUPLICATE KEY UPDATE) you will need to refactor database a bit and SQL will look like next, (safe for transactions and no transactions inside one connection.)
#START TRANSACTION
INSERT INTO bulk_inserts VALUES (null);
SET #blukTransactionId = LAST_INSERT_ID();
SELECT #blukTransactionId, LAST_INSERT_ID();
INSERT INTO `main_table` (`value`, `transaction_id`) VALUES ('first', #blukTransactionId), ('second', #blukTransactionId) ON DUPLICATE KEY UPDATE `value` = VALUES(`value`), `transaction_id` = VALUES(`transaction_id`);
SELECT #blukTransactionId, LAST_INSERT_ID();
SELECT id FROM `main_table` WHERE `transaction_id` = #blukTransactionId;
#COMMIT
both cases are safe to transnational. first will show you only inserted records and second will give you all records even updated.
also those options will work even with INSERT IGNORE ...
This thread is old but all these solutions did not help me so I came up with my own.
First, count how many rows you want to insert
let's say we need to add 5 rows:
LOCK TABLE tbl WRITE;
SELECT `AUTO_INCREMENT` FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'my_db' AND TABLE_NAME = 'tbl'
then use the auto_increment just selected to do next query:
ALTER TABLE tbl AUTO_INCREMENT = {AUTO_INCREMENT}+5;
UNLOCK TABLES;
Finally do your inserts
Use the reserved autoincrement range to insert with id.
Warning: this solution requires elevated access level to the tables. But usually bulk inserts are run by crons and importer scripts and what not that may use special access anyway. You would not use this for just a few inserts.
This may leave unused id's if you use ON DUPLICATE KEY UPDATE.
I think you will have to either handle the transaction id in your application, or the item id in your application in order to do this flawlessly.
One way to do this which could work, assuming that all your inserts succeed (!), is the following :
You can then get the inserted id's with a loop for the number of affected rows, starting with lastid (which is the first inserted id of the bulk insert).
And thus, i checked it works perfectly .. just be careful that HeidiSQL for example will not return the correct value for ROW_COUNT(), probably because it's a crappy GUI doing random shit we don't ask it - however it's perfectly correct from either command line or PHP mysqli -
START TRANSACTION;
BEGIN;
INSERT into test (b) VALUES ('1'),('2'),('3');
SELECT LAST_INSERT_ID() AS lastid,ROW_COUNT() AS rowcount;
COMMIT;
In PHP it looks like this (local_sqle is a straight call to mysqli_query, local_sqlec is a call to mysqli_query + convert resultset to PHP array) :
local_sqle("START TRANSACTION;
BEGIN;
INSERT into test (b) VALUES ('1'),('2'),('3');");
$r=local_sqlec("SELECT LAST_INSERT_ID() AS lastid,ROW_COUNT() AS rowcount;");
local_sqle("
COMMIT;");
$i=0;
echo "last id =".($r[0]['lastid'])."<br>";
echo "Row count =".($r[0]['rowcount'])."<br>";
while($i<$r[0]['rowcount']){
echo "inserted id =".($r[0]['lastid']+$i)."<br>";
$i++;
}
The reason the queries are separated is because I wouldn't otherwise get my result using my own functions, if you do this with standard functions, you can put it back in one statement and then retrieve the result you need (it should be result number 2 - assuming you use an extension which handles more than one result set / query).
For anyone using java with JDBC, it is possible. I am getting ids back with batch-insert doing it like this:
PreparedStatement insertBatch = null;
Connection connection = ....;
for (Event event : events) {
if (insertBatch == null){
insertBatch = connection.prepareStatement("insert into `event` (game, `type`, actor, target, arg1, arg2, arg3, created) " +
"values (?, ?, ?, ?, ?, ?, ?, ?)", Statement.RETURN_GENERATED_KEYS);
}
insertBatch.setObject(1, event.game);
insertBatch.setString(2, event.type);
insertBatch.setObject(3, event.actor);
insertBatch.setObject(4, event.target);
insertBatch.setString(5, event.arg1);
insertBatch.setObject(6, event.arg2);
insertBatch.setObject(7, event.arg3);
insertBatch.setTimestamp(8, new Timestamp(event.created.getTime()));
insertBatch.addBatch();
}
}
if (insertBatch != null){
insertBatch.executeBatch();
ResultSet generatedKeys = insertBatch.getGeneratedKeys();
for (Event event : events) {
if ( generatedKeys == null || ! generatedKeys.next()){
logger.warn("Unable to retrieve all generated keys");
}
event.id = generatedKeys.getLong(1);
}
logger.debug("events inserted");
}
Source: "Using MySQL I can do it with JDBC this way:" - Plap - https://groups.google.com/g/jdbi/c/ZDqnfhK758g?pli=1
I have to actually add this to my JDBC url: rewriteBatchedStatements=true. Or else the actual inserts show up in the mysql "general query log" as separate rows. With 7000 rows inserted, I got 2m11s for regular inserts, 46s without rewrite.. on and 1.1s with rewrite.. on. Also, it does not make other people's inserts block (I tested that). When I inserted 200k rows, it grouped them into about 36k per line ie insert into abc(..) values(..),(..),(..)....
I am actually using JDBCTemplate so the way to access the PreparedStatement is:
ArrayList<Long> generatedIds = (ArrayList<Long>) jdbcTemplate.execute(
new PreparedStatementCreator() {
#Override
public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
return connection.prepareStatement(insertSql, Statement.RETURN_GENERATED_KEYS);
}
},
new PreparedStatementCallback<Object>() {
#Override
public Object doInPreparedStatement(PreparedStatement ps) throws SQLException, DataAccessException {
// see above answer for setting the row data
...
ps.executeBatch();
ResultSet resultSet = ps.getGeneratedKeys();
ArrayList<Long> ids = new ArrayList<>();
while (resultSet.next()) {
ids.add(resultSet.getLong(1));
}
return ids;
}
}
);
$query = "INSERT INTO TABLE (ID,NAME,EMAIL) VALUES (NULL,VALUE1, VALUE2)";
$idArray = array();
foreach($array as $key) {
mysql_query($query);
array_push($idArray, mysql_insert_id());
}
print_r($idArray);
$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)");
I am trying to retrieve the auto increment value of last inserted data in mySQL. Here is my code:
public int getAutoIncrementProductID() {
ResultSet rs = null;
DBController db = new DBController();
db.getConnection();
int autoIncKeyFromFunc = -1;
rs = db.readRequest("SELECT LAST_INSERT_ID()");
try {
if (rs.next()) {
autoIncKeyFromFunc = rs.getInt(1);
System.out.println("AUTO ID IS " + autoIncKeyFromFunc);
rs.close();
}
} catch (Exception e) {
e.printStackTrace();
}
db.terminate();
return autoIncKeyFromFunc;
}
However, these codes keep returning me 0 value although the auto increment column in database is keep increasing. It just wont get the auto increment value of last inserted data. Anybody could help?
You should use LAST_INSERT_ID() after you insert something.
For LAST_INSERT_ID(), the most recently generated ID is maintained in
the server on a per-connection basis. It is not changed by another
client. It is not even changed if you update another AUTO_INCREMENT
column with a nonmagic value (that is, a value that is not NULL and
not 0).
Source
You may also try
SELECT max(id) FROM tableName
But it will not suppose deleted rows.
How about this?
SELECT your_id FROM your_table ORDER BY your_id DESC LIMIT 1
I think since you are using Jdbc there is another way to get generated key is to use API connection. createStatement (Statement.RETURN_GENERATED_KEYS); Look at this thread PreparedStatement with Statement.RETURN_GENERATED_KEYS
I use this:
SELECT auto_increment + 1 AS NEXT_ID
FROM `information_schema`.`tables`
WHERE table_name = "table_name"
AND table_schema = "database_name"
Be Careful when using mysql_insert_id() specially if you have multiple connections to the Database. Because It doesn't get the value of the query you've inserted. it gets the latest id of the table. It may be a row another query has inserted. Only use this function if you access Database in one connection.
If you want to get the id of the query you've inserted, try to select the row with an unique value you've inserted with that query. Ex : finding the user id of a user with his email address.
SELECT id from users where emailaddress='me#johndoe.com' LIMIT 1
More details here :
https://www.php.net/manual/en/function.mysql-insert-id.php
How about this?
SHOW TABLE STATUS FROM Database_Name LIKE 'TableName' ;
On my db-server i am inserting data in a table having a auto increment field say 'id'. Now i want to use the value of this last inserted 'id' in subsequent steps. I can use this:-
select * from table_name order by id desc limit 1;
But the problem here is, it is a server and many more insertions could be happening and there could be a case where i try to retrieve the data with the query i mentioned and get a different id ie. between my insert and select there could be some other insert and i wont get the value i inserted. Any way in which this could be addressed.?
Thanks in advance.
Use this
mysql_insert_id(&mysql);
as its basic structure are
mysql_insert_id ([ resource $link_identifier = NULL ] )
Retrieves the ID generated for an AUTO_INCREMENT column by the previous query (usually INSERT).
or in mysql use
SELECT LAST_INSERT_ID();
here is the ref links
http://dev.mysql.com/doc/refman/5.0/en/getting-unique-id.html
http://php.net/manual/en/function.mysql-insert-id.php
try this
SELECT LAST_INSERT_ID(colid) From tablename;
heres the Link
call LAST_INSERT_ID() function immediately after insertion and save id somewhere.
Use this mysql_insert_id()
It returns the AUTO_INCREMENT ID generated from the previous INSERT operation.
This function returns 0 if the previous operation does not generate an AUTO_INCREMENT ID, or FALSE on MySQL connection failure.
you can get the id if you call LAST_INSERT_ID() function immediately after insertion and then you can use it.
For any last inserted record will be get through mysql_insert_id()
If your table contain any AUTO_INCREMENT column it will return that Value.
mysql_query("INSERT INTO test(emsg,etime) values ('inserted',now())");
printf("Last inserted record has id %d\n", mysql_insert_id());
$last_id=mysql_insert_id();
echo $last_id;
?>
I know how LAST_INSERT_ID() works for auto incremented columns, but I cannot find a way to get the last id I inserted for a non auto incremented column.
Is there a way I can do that?
you can easily do that using the same LAST_INSERT_ID().
INSERT INTO thetable (id, value)
VALUES (LAST_INSERT_ID(126), 'some data');
SELECT LAST_INSERT_ID(); -- returns 126
I'm assuming you want the retrieve this last inserted id at some later point after inserting it, since if you need it right after inserting it you obviously would already know what the id is.
The only way you'll be able to get that is to have another column on the table that can indicate which row was last inserted, such as a timestamp or datetime column. If your ids are unique and increasing, you can just use that column. Then you just select 1 row ordered by that column in descending order.
For example
INSERT INTO my_table (id, timestamp) VALUES (123, NOW())
SELECT id FROM my_table ORDER BY timestamp DESC LIMIT 1
Edit: as per the comments below, you're much better off using an AUTO_INCREMENT column, though this column doesn't have to be the id column, you could add an auto-increment insert_order column of type Int and simply order by that.
I assume that you need the ID to find your just inserted row, rather to find the last inserted row. In a web application, you can never be sure that the last inserted row is the one you have just created.
You could use a GUID as id in this case. A GUID is usually stored as a string of length 36 or as a 16byte blob. The GUID can be created before inserting the row, and then can be stored while inserting the row.
Since the id is not auto incremented as you stated, you have to generate it anyway before inserting the row. The safest way to do this is to create a GUID which should be unique enough. Otherwise you would have to determine the last unused ID, what can be tricky and risky.
The easiest way I found to do this is to set a variable.
Unlike using LAST_INSERT_ID which only returns and INT this way you can use other unique identifiers.
SET #id = UUID();
INSERT INTO users (
id
)
VALUES (
#id
);
SELECT * FROM users WHERE id = #id;
No.
There is no inherent ordering of relations, no "last-inserted record". This is why the AUTO_INCREMENT field exists, after all.
You'd have to look in logs or cache the value yourself inside your application.
There's no way with mysql. But you can to do it programmatically. Without an auto-incrementing ID column there's no way for the database to know which records were inserted last.
One way to do is use such as a column containing timestamp or datetime values. and get id of latest value of tmestamp to get last inserted record
If you want to get a custom last_inserted ID, you must implement a procedure that will make the insert statment on your DB.
At the end, just print the ID and use the PHP (if PHP is your main script) sender to return the generated row.
EXAMPLE:
DROP PROCEDURE IF EXISTS insert_row;
DELIMITER $$
CREATE PROCEDURE insert_row(IN _row_id VARCHAR(255), IN _description VARCHAR(255))
BEGIN
SET #last_inserted_id = _row_id;
SET #sql = CONCAT("INSERT INTO test VALUES ('", _row_id, "','",_description,"')");
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SELECT #last_inserted_id AS LAST_INSERT_ID;
END;
$$
DELIMITER ;
#
#
#
#------- HOW TO USE IT ? ---------------
CALL insert_row('Test001','the first test line');
This worked for me in XAMPP
$qry = $con->query("INSERT INTO test_table(tbl_id, txt) VALUES(last_insert_id('15'), 'test value')");
print_r($con->insert_id);