get the last ID after insert in mysql - mysql

how can i get the ID of the last insert statement
im using trigger to create a ID for every record
INSERT INTO table1_seqdocument VALUES (NULL);
SET NEW.tracknum = CONCAT('DOC', LPAD(LAST_INSERT_ID(), 3, '0'));
and i need that ID for other table
this is this my insert statement
INSERT INTO tble_transaction
(
tracknum
,signatoryid
,signed
,status
,signatorylevel
)
VALUES
(?,?,?,?,? )
what i want is to retrieve the ID and use it for another insert statement but using other table. is it possible? thank you

You can use ##identity
SELECT ##IDENTITY AS [##IDENTITY];

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.)

Related

Can you combine INSERT INTO and Last_Insert_ID in one SQL Statement

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

INSERT and then SELECT the inserted row

My table Structure,Table Name- user_tb
User_Id Name Mob_No City
=================================
100 Sumith 34542 dfsc
101 Yadhu 35485 dfgd
102 Aby 34234 jhhg
Here column User_Id is auto_increment
and am inserting values to this table using this query,
insert into user_tb(Name,Mob_No,City) values('Yadhu',34542,'dfsc');
I need to get User_Id of the Person at the time of insertion
ie, when am inserting using this query,
insert into user_tb(Name,Mob_No,City) values('Yadhu',34542,'dfsc');
i need to get User_id-101
Is this possible....
Anyone please help me to complete this.
Obtaining the value of column that uses AUTO_INCREMENT after an INSERT statement can be achieved in a number of different ways. To obtain the value immediately after an INSERT, use a SELECT query with the LAST_INSERT_ID() function.
For example, using Connector/ODBC you would execute two separate statements, the INSERT statement and the SELECT query to obtain the auto-increment value.
insert into user_tb(Name,Mob_No,City) values('Yadhu',34542,'dfsc');
SELECT LAST_INSERT_ID();
If you do not require the value within your application, but do require the value as part of another INSERT, the entire process can be handled by executing the following statements:
insert into user_tb(Name,Mob_No,City) values ('Yadhu',34542,'dfsc');
insert into tbl2 (id,text) VALUES (LAST_INSERT_ID(),'text');
In Mysql: use LAST_INSERT_ID() function; http://dev.mysql.com/doc/refman/5.0/en/mysql-insert-id.html
If PHP: use mysql_insert_id() to get the last id inserted by your query.
http://php.net/manual/en/function.mysql-insert-id.php

Insert only when auto-increment id is not equal 6(for example)?

I have a table with 3 fields: Id(PK,AI), Name(varchar(36)), LName(varchar(36)).
I have to insert name and last name, Id inserts automatically because of it's constraints,
Is There a way to Jump id auto increment value when it reaches 6?
for instance do this 7 times:
Insert Into table(Name, LName) Values ('name1', 'lname1') "And jump id to 7 if it is going to be 6"
It may sound stupid to do this but I have the doubt.
Also Jump and do not record id 6.
record only, 1-5, 7,8,9 and so on
What I want to achieve starts from a Union:
Select * From TableNames
Union All
Select * From TableNames_general
In the TableNames_general I assign it's first value so that when the user sees the table for the first time it will be displayed the record I inserted.
The problem comes when the user inserts a new record, if the Id of the inserted record is the same as the one I have inserted it will be duplicated, that is why I want to achieve when the users inserts one record and if the last insert id already exists just jump that record. this is because I must have different ids due to its relationship among child tables.
Identity column generate values for you, And its best left this way, You have the ability to insert specific values in Identity column but its best left alone and let it generate values for you.
Imagine you have inserted a value explicitly in an identity column and then later on Identity column generates the same value for you, you will end up with duplicates.
If you want to have your input in that column then why bother with identity column anyway ??
Well this is not the best practice but you can jump to a specific number by doing as follows:
MS SQL SERVER 2005 and Later
-- Create test table
CREATE TABLE ID_TEST(ID INT IDENTITY(1,1), VALUE INT)
GO
-- Insert values
INSERT INTO ID_TEST (VALUE) VALUES
(1),(2),(3)
GO
-- Set idnentity insert on to insert values explicitly in identity column
SET IDENTITY_INSERT ID_TEST ON;
INSERT INTO ID_TEST (ID, VALUE) VALUES
(6, 6),(8,8),(9,9)
GO
-- Set identity insert off
SET IDENTITY_INSERT ID_TEST OFF;
GO
-- 1st reseed the value of identity column to any smallest value in your table
-- below I reseeded it to 0
DBCC CHECKIDENT ('ID_TEST', RESEED, 0);
-- execute the same commad without any seed value it will reset it to the
-- next highest idnetity value
DBCC CHECKIDENT ('ID_TEST', RESEED);
GO
-- final insert
INSERT INTO ID_TEST (VALUE) VALUES
(10)
GO
-- now select data from table and see the gap
SELECT * FROM ID_TEST
If you query the database to get the last inserted ID, then you can check if you need to increment it, by using a parameter in the query to set the correct ID.
If you use MSSQL, you can do the following:
Before you insert check for the current ID, if it's 5, then do the following:
Set IDENTITY_INSERT to ON
Insert your data with ID = 7
Set IDENTITY_INSERT to OFF
Also you might get away with the following scenario:
check for current ID
if it's 5, run DBCC CHECKIDENT (Table, reseed, 6), it will reseed the table and in this case your next identity will be 7
If you're checking for current identity just after INSERT, you can use SELECT ##IDENTITY or SELECT SCOPE_IDENTITY() for better results (as rcdmk pointed out in comments)
Otherwise you can just use select: SELECT MAX(Id) FROM Table
There's no direct way to influence the AUTO_INCREMENT to "skip" a particular value, or values on a particular condition.
I think you'd have to handle this in an AFTER INSERT trigger. An AFTER INSERT trigger can't update the values of the row that was just inserted, and I don't think it can make any modifications to the table affected by the statement that fired the trigger.
A BEFORE INSERT trigger won't work either, because the value assigned to an AUTO_INCREMENT column is not available in a BEFORE INSERT trigger.
I don't believe there's a way to get SQL Server IDENTITY to "skip" a particular value either.
UPDATE
If you need "unique" id values between two tables, there's a rather ugly workaround with MySQL: roll your own auto_increment behavior using triggers and a separate table. Rather than defining your tables with AUTO_INCREMENT attribute, use a BEFORE INSERT trigger to obtain a value.
If an id value is supplied, and it's larger than the current maximum value from the auto_increment column in the dummy auto_increment_seq table, we'd need to either update that row, or insert a new one.
As a rough outline:
CREATE TABLE auto_increment_seq
(id INT NOT NULL PRIMARY KEY AUTO_INCREMENT) ENGINE=MyISAM;
DELIMITER $$
CREATE TRIGGER TableNames_bi
BEFORE INSERT ON TableNames
FOR EACH ROW
BEGIN
DECLARE li_new_id INT UNSIGNED;
IF ( NEW.id = 0 OR NEW.id IS NULL ) THEN
INSERT INTO auto_increment_seq (id) VALUES (NULL);
SELECT LAST_INSERT_ID() INTO li_new_id;
SET NEW.id = li_new_id;
ELSE
SELECT MAX(id) INTO li_max_seq FROM auto_increment_seq;
IF ( NEW.id > li_max_seq ) THEN
INSERT INTO auto_increment_seq (id) VALUES (NEW.id);
END IF;
END IF;
END$$
CREATE TRIGGER TableNames_ai
AFTER INSERT ON TableNames
FOR EACH ROW BEGIN
DECLARE li_max_seq INT UNSIGNED;
SELECT MAX(id) INTO li_max_seq FROM auto_increment_seq;
IF ( NEW.id > li_max_seq ) THEN
INSERT INTO auto_increment_seq (id) VALUES (NEW.id);
END IF;
END;
DELIMITER ;
The id column in the table could be defined something like this:
TableNames
( id INT UNSIGNED NOT NULL DEFAULT 0 PRIMARY KEY
COMMENT 'populated from auto_increment_seq.id'
, ...
You could create an identical trigger for the other table as well, so the two tables are effectively sharing the same auto_increment sequence. (With less efficiency and concurrency than an Oracle SEQUENCE object would provide.)
IMPORTANT NOTES
This doesn't really insure that the id values between the tables are actually kept unique. That would really require a query of the other table to see if the id value exists or not; and if running with InnoDB engine, in the context of some transaction isolation levels, we might be querying a stale (as in, consistent from the point in time at the start of the transaction) version of the other table.
And absent some additional (concurrency killing) locking, the approach outline above is subject to a small window of opportunity for a "race" condition with concurrent inserts... the SELECT MAX() from the dummy seq table, followed by the INSERT, allows a small window for another transaction to also run a SELECT MAX(), and return the same value. The best we can hope for (I think) is for an error to be thrown due to a duplicate key exception.
This approach requires the dummy "seq" table to use the MyISAM engine, so we can get an Oracle-like AUTONOMOUS TRANSACTION behavior; if inserts to the real tables are performed in the context of a REPEATABLE READ or SERIALIZABLE transaction isolation level, reads of the MAX(id) from the seq table would be consistent from the snapshot at the beginning of the transaction, we wouldn't get the newly inserted (or updated) values.
We'd also really need to consider the edge case of an UPDATE of row changing the id value; to handle that case, we'd need BEFORE/AFTER UPDATE triggers as well.

Trouble with MAX(col)+1 INSERT into same MySQL table

I need two id columns in the same table that create unique values upon insert. Since MySQL allows only one column to auto-increment, I need to do something like max(id)+1 for the other column.
Here's the SQL I expected to work:
INSERT INTO invoices (invoiceid)
VALUES ((SELECT MAX(invoiceid)+1 FROM invoices))
The select statement works independently, but within my INSERT, it's not allowed. I get the error : You can't specify target table 'invoices' for update in FROM clause
You want to use INSERT INTO .... SELECT FROM instead of INSERT INTO...VALUES():
INSERT INTO invoices (invoiceid)
SELECT MAX(invoiceid)+1
FROM invoices
My question for you would be why are you not use an AUTO INCREMENT field to generate the invoiceid value? That is what it is for, then you will not have to create this when inserting data.

Is there a way to get last inserted id of a NON - auto incremented column in MySQL?

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);