SELECT LAST_INSERT_ID() as id FROM table1
Why does this query sometimes return the last inserted id of another table other than table1?
I call it in Node.js (db-mysql plugin) and I can only do queries.
LAST_INSERT_ID() can only tell you the ID of the most recently auto-generated ID for that entire database connection, not for each individual table, which is also why the query should only read SELECT LAST_INSERT_ID() - without specifying a table.
As soon as you fire off another INSERT query on that connection, it gets overwritten. If you want the generated ID when you insert to some table, you must run SELECT LAST_INSERT_ID() immediately after doing that (or use some API function which does this for you).
If you want the newest ID currently in an arbitrary table, you have to do a SELECT MAX(id) on that table, where id is the name of your ID column. However, this is not necessarily the most recently generated ID, in case that row has been deleted, nor is it necessarily one generated from your connection, in case another connection manages to perform an INSERT between your own INSERT and your selection of the ID.
(For the record, your query actually returns N rows containing the most recently generated ID on that database connection, where N is the number of rows in table1.)
SELECT id FROM tableName ORDER BY id DESC LIMIT 1
I usually select the auto-incremented ID field, order by the field descending and limit results to 1. For example, in a wordpress database I can get the last ID of the wp_options table by doing:
SELECT option_id FROM wp_options ORDER BY option_id DESC LIMIT 1;
Hope that helps.
Edit - It may make sense to lock the table to avoid updates to the table which may result in an incorrect ID returned.
LOCK TABLES wp_options READ;
SELECT option_id FROM wp_options ORDER BY option_id DESC LIMIT 1;
Try this. This is working
select (auto_increment-1) as lastId
from information_schema.tables
where table_name = 'tableName'
and table_schema = 'dbName'
Most easy way:
select max(id) from table_name;
I only use auto_increment in MySQL or identity(1,1) in SQL Server if I know I'll never care about the generated id.
select last_insert_id() is the easy way out, but dangerous.
A way to handle correlative ids is to store them in a util table, something like:
create table correlatives(
last_correlative_used int not null,
table_identifier varchar(5) not null unique
);
You can also create a stored procedure to generate and return the next id of X table
drop procedure if exists next_correlative;
DELIMITER //
create procedure next_correlative(
in in_table_identifier varchar(5)
)
BEGIN
declare next_correlative int default 1;
select last_correlative_used+1 into next_correlative from correlatives where table_identifier = in_table_identifier;
update correlatives set last_correlative_used = next_correlative where table_identifier = in_table_identifier;
select next_correlative from dual;
END //
DELIMITER ;
To use it
call next_correlative('SALES');
This allows you to reserve ids before inserting a record. Sometimes you want to display the next id in a form before completing the insertion and helps to isolate it from other calls.
Here's a test script to mess around with:
create database testids;
use testids;
create table correlatives(
last_correlative_used int not null,
table_identifier varchar(5) not null unique
);
insert into correlatives values(1, 'SALES');
drop procedure if exists next_correlative;
DELIMITER //
create procedure next_correlative(
in in_table_identifier varchar(5)
)
BEGIN
declare next_correlative int default 1;
select last_correlative_used+1 into next_correlative from correlatives where table_identifier = in_table_identifier;
update correlatives set last_correlative_used = next_correlative where table_identifier = in_table_identifier;
select next_correlative from dual;
END //
DELIMITER ;
call next_correlative('SALES');
If you want to use these workarounds:
SELECT id FROM tableName ORDER BY id DESC LIMIT 1
SELECT MAX(id) FROM tableName
It's recommended to use a where clause after inserting rows. Without this you are going to have inconsistency issues.
in my table inv_id is auto increment
for my purpose this is worked
select `inv_id` from `tbl_invoice`ORDER BY `inv_id` DESC LIMIT 1;
Related
I have a table in MYSQL database with two fields:
Id (auto increment field).
Post_Id.
When I insert a new record both fields should have the same value. So I should update post_id with Id value, and at the same time make sure that I update the field with the right value not with any other new inserted record value.
I tried this SQL statement but it was very slow and I was not sure that I select the right value:
set #auto_id := (SELECT AUTO_INCREMENT
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME='table_name'
AND TABLE_SCHEMA=DATABASE() );
update table_name set post_id= #auto_id where id=#auto_id ;
I don't have long experience with MySQL and I cannot change the table structure .
The approach you followed is not transaction safe as well.
The best option I can think about is to use trigger
Edit: According to #lagripe's mentionings
CREATE TRIGGER sometrigger
AFTER INSERT ON sometable
BEGIN
SET NEW.post_id := (SELECT id from sometable order by DESC limit 1) + 1 ; // you may need +1 here. I couldn't test it.
END
or you may consider to use LAST_INSERT_ID
insert into table_name values ( .... );
update table_name set post_id = LAST_INSERT_ID();
but why do you need two columns with the same id at first place?
if you really need why don't you use computed/generated columns?
CREATE TABLE Table1(
id DOUBLE,
post_id DOUBLE as (id)
);
you can use triggers :
CREATE TRIGGER UpdatePOST_id
BEFORE INSERT ON table_db
FOR EACH ROW
SET NEW.post_id := (select id from table_db order by id DESC LIMIT 1)+1 ;
from now on, whatever you insert your as a value in post_id column will be replaced with the id inserted automatically.
Test :
|id|post_id|
|20| 20 |
|21| 21 |
|22| 22 |
|23| 23 |
To drop the trigger :
DROP trigger UpdatePOST_id
I want to get the value of the last id insert in a table. How i can do this in mysql?
For eg : in db2 we have
SET var_ID = (SELECT ID FROM NEW TABLE (INSERT INTO val_CLIENT(E_VER, NAME, TYPE) VALUES(0, val_NAME, 502)));
The above statement needs to be converted into mysql. How can i do this?
You can use the LAST_INSERT_ID() function.
Do your insert statement:
INSERT INTO val_CLIENT(E_VER, NAME, TYPE) VALUES(0, val_NAME, 502);
Depending if you're doing it in a stored procedure, you will have to modify this, but if you're looking to select it.
SELECT LAST_INSERT_ID() AS `ID`;
To store it as a variable, you can use the SET statement.
SET #VarID = (SELECT LAST_INSERT_ID());
If your ID column is of type AUTO_INCREMENT, Use LAST_INSERT_ID() after the INSERT statement
SELECT LAST_INSERT_ID() as ID
However, for concurrent requests using same connection, this will lead into inconsistent result. In that case, the following query is a safe bet:
SELECT ID FROM val_CLIENT
ORDER BY ID DESC
LIMIT 1
A possible query:
SELECT id FROM tableORDER BY id DESC LIMIT 1
I'm quite new to SQL and databases.
I'm trying to make a preference table of an user.
The fields will be user_id, pref_no, prg_code.
Now if I create the table making pref_no auto_increment then it will automatically increase irrespective of the user_id.
So, my question is - Is there a way to define the table in such a way that it will be auto_incremented taking user_id into account or I have to explicitly find the last pref_no that has occurred for an user and then increment it by 1 before insertion?
Any help is appreciated. Thanks in advance.
Following what Mjh and Fahmina suggested, we can create a procedure for the insertion.
DELIMITER //
CREATE PROCEDURE test(IN u_id INT(7), p_code INT(5))
BEGIN
SELECT #pno:= MAX(pref_no) FROM temp_choice WHERE user_id = u_id;
IF #pno IS NULL THEN
SET #pno = 1;
ELSE
SET #pno = #pno + 1;
END IF;
INSERT INTO temp_choice VALUES (u_id, #pno, p_code);
END //
DELIMITER ;
Now we can easily insert data by using
CALL test(1234567, 10101);
To manage user's preference, you don't need user_id to be auto_incremented in this table, but pref_no has to be.
user_id will just be a refence (or foreign key in sql) to your user table (where user_id should be auto_incremented).
And to request preference for a given user your request would be :
SELECT * FROM [user table] INNER JOIN [pref table] ON ([user table].user_id = [pref table].user_id) WHERE [user table].user_id = ?
(replace '?' by the user_id you want)
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);
I'm trying to implement a custom sort field for a list of records. When I create a new record, by default I would like this field to match the ID number of that record. Is there any way to achieve this without having to perform two queries?
Any advice appreciated.
Thanks
You can get the next auto-increment id by using
SHOW TABLE STATUS FROM tablename LIKE Auto_increment
/*or*/
SELECT `auto_increment` FROM `INFORMATION_SCHEMA.TABLES` WHERE table_name = 'tablename'
This will give you the next auto_increment value.
Then make a before insert trigger:
DELIMITER $$
CREATE TRIGGER bi_table1_each BEFORE INSERT ON table1 FOR EACH ROW
BEGIN
DECLARE next_id integer;
SELECT `auto-increment` FROM `INFORMATION_SCHEMA.TABLES` INTO Next_id
WHERE TABLE_NAME = 'table1' LIMIT 1;
SET new.sortcolumn = next_id;
END $$
DELIMITER ;
Links
http://dev.mysql.com/doc/refman/5.1/en/show-table-status.html
http://dev.mysql.com/doc/refman/5.0/en/tables-table.html
http://dev.mysql.com/doc/refman/5.0/en/triggers.html
http://dev.mysql.com/doc/refman/5.0/en/create-trigger.html
I think you can leave this field equal to NULL by default and then in your query do this:
ORDER BY ifnull(sort_field, id)
Set it to null or something like that by default and make your query sort by id if the sort field is null. PseudoSQL:
SELECT blah, IFNULL(t.sort, t.id) AS sortval
FROM t
ORDER BY sortval
You can use MAX(ID) expression to be sure that your next INSERT will be the greater id + 1 :
INSERT INTO table_name (..., sort_field) VALUES (..., MAX(id)+1)
Hope this helps, bye!