Getting last inserted UniqueId from MySQL - php

I'm inserting records, primary key is a uniqueId created by PHP.
How to retrieve last inserted uniqueId from MySQL?
Tnx

If it is an auto_incremented value you would use mysql_insert_id() (or its mysqli sibling) immediately after doing an insert to get the ID assigned to it.
If you wanted to get a non-auto incremented value you would need to SELECT the row with the highest value and sort by that value in descending order to do the job (assuming it is numeric or alphanumeric and increments sequentially):
SELECT id FROM tablename ORDER id DESC LIMIT 1
If it is a random ID than you would need to sort by date:
SELECT id FROM tablename ORDER datecol DESC LIMIT 1
If you don't have any other method of sorting these records you can get the last row in the table but there is no guarantee that record is the newest and thus you have no accuracy in your results.

Related

UNION mysql determine which table the result came from

$stmt = $dbh->prepare("SELECT id FROM table1 UNION SELECT id FROM table2 UNION SELECT id FROM table3 ORDER BY id DESC LIMIT 1");
The code above is my code for auto generating ID. I want to select the last inserted ID. What I want to do is I want to get the last ID inserted on three tables. It can be from any of the three tables. And then i want to increment that ID. But the catch is i need to know which table the last ID is from so i can select another field and record that the last ID has a certain attribute. This attribute is depending on the table that is why i want to get the table.
Add a discriminator column, and use the MAX aggregate function for each query to avoid sorting a huge intermediate resultset, and use UNION ALL set operator in place of UNION operator. (Since each query will return only one row, that's not going to make much of a difference; but where we don't need to eliminate duplicate rows, we prefer the UNION ALL set operator to avoid the unnecessary (and sometimes expensive) operation.
Something like this should return the result you seem to be after:
( SELECT 'table1' AS source
, MAX(t1.id) AS max_id
FROM table1 t1
)
UNION ALL
( SELECT 'table2' AS source
, MAX(t2.id) AS max_id
FROM table2 t2
)
UNION ALL
( SELECT 'table3' AS source
, MAX(t3.id) AS max_id
FROM table3 t3
)
ORDER BY max_id DESC
LIMIT 1
That will give you a resultset that identifies the table name that had the maximum id.
NOTE: This assumes that the "last inserted id" is identified by the maximum value. If two tables have the same maximum id value, it's indeterminate which row will be returned. You can add source to the ORDER BY to make it deterministic:
ORDER BY max_id DESC, source DESC
(The actual requirements aren't clear to me; the statement above should return the same value that was being returned by the query in the question, along with a discriminator which tells which table the id value is from.)
Reference: https://dev.mysql.com/doc/refman/5.5/en/union.html
NOTE: This may satisfy your use case, but in the more general case, we advise avoiding this approach to get the id value of the row that was last inserted.
For values of an auto_increment column, where the value is automatically assigned, the last_insert_id function will return the id value of the first row that was inserted by the immediately preceding INSERT statement in the same session. In a multiuser system, it is not safe to assume that the "highest" id value was a row inserted by the current session - that approach is effectively broken.
Try to get last inserted ID of all three tables and with inserted time then differentiate based on inserted time

How to select unique value randomly from a table in heavy load server

I have a single-column MySQL database table ids (id INTEGER PRIMARY KEY AUTOINCREMENT) where I store pre-generated unique ids in an ascending order. In order to get a random id from that table I use this query:
SELECT id FROM ids ORDER BY RAND() LIMIT 1;
And now I am wondering how to ensure that the id I got is never used again. I see two options. One is to delete the id from the table and the other is add a column tracking the use of that id:
DELETE FROM ids WHERE id=?; //where id is the one I got from the previous query
or
SELECT id FROM ids WHERE used=0 ORDER BY RAND() LIMIT 1;
UPDATE ids SET used=1 WHERE id=?; //where used is new column with 0 as default value
There is only a slight problem with both of these. If the server load is heavy then two queries for a random id might return the same id before it gets removed from the list (or disabled with used column).
Would transaction help?
Wrapping your select and your update in a transaction will work. If you want to avoid a transaction as well as the race condition between selecting your item and marking it unusable, you can run the UPDATE first. You'll need a way for each of your processes to identify itself as the owner of the row between claiming it and deletion. For example, assume your ids schema is
id (integer)
owner (string)
Have each process pick a UUID (or something else suitably unique) and run the following:
UPDATE ids SET owner = $process_id WHERE owner IS NULL ORDER BY RAND() LIMIT 1
SELECT id FROM ids WHERE owner = $process_id
DELETE FROM ids WHERE id = $selected_id (or otherwise mark it used)
Step 1 atomically claims the row for the process so that no other process can claim it. Step 2 pulls out the claimed ID. Step 3 removes the ID from the available set for good. If Step 3 doesn't delete the row, just marks it used, make sure you clear owner as well so your process won't select it again later.
Add an extra column to your ids table. Let us say selected. You will update this column when it is generated in your randomized query.
1 for selected and 0 for not yet.
For example
SELECT id FROM ids ORDER BY RAND() WHERE selected = 0 LIMIT 1;
$id = $row['id']; /* STORE THE SELECTED ID TO A VARIABLE */
Then update the table with
UPDATE ids SET selected = 1 WHERE id = $id
So that your next run of your randomized query will only get the row of selected 0 value, and not the one with 1 value.
you could try updating the id 1st before selecting it. try this one.
-- get firstID
SELECT #MinID:=id FROM ids ORDER by id ASC LIMIT 1;
-- get last id
SELECT #MaxID:=id FROM ids ORDER by id DESC LIMIT 1;
-- get random id
SELECT #rndomID :=ROUND((RAND() * (#MaxID-#MinID))+#MinID);
-- update first
UPDATE ids SET used=1 WHERE id=#rndomID;
-- select the id
SELECT id FROM ids WHERE used=0 WHERE id=#rndomID;

how can I show the specific column value of last rows oh mysql database and print as a table

I have a table which keeps the track of user orders . I want to show the user a invoice , hence I need to print the specific column value of last records . How can I do that ?
I'm assuming you have some sort of date or id column to sort the records by so you can identify the last row
SELECT column FROM records ORDER BY id DESC LIMIT 1
In the deplorable event you lack some sort of id to sort the rows by, you can try this in php or some equivalent language:
SELECT COUNT(*) FROM records
//set this as variable x
SELECT column FROM records WHERE 1 LIMIT x-1,1

How to maintain proper number order in mysql auto increment field when delete rows

I have a table A which has a auto increment serial number field SLNO. When i insert values in table it will increment automatically like 1,2,3,4... etc. But when i delete a row from the table the order get break. ie, if delete row with serial number 2 then the serial number field will 1,3,4. But I want to maintain a continuous order like 1,2,3 even delete rows. Is there any way to maintain this order, like using trigger or somthing
A primary auto-increment key is only for uniquely identifying a record. Just leave it be.
Don't misuse the primary key as indicator of your record order. If you need specific order of your records then use an extra column for that. For instance a timestamp column.
If you need a specific order of your records use a timestamp column with a default value of current_timestamp. That way it will be inserted automatically.
ALTER TABLE your_table
ADD column inserted_timestamp TIMESTAMP default current_timestamp;
SQLFiddle demo
You should leave it as it is.
However, if you do really need, you can "recalculate" the primary key, the index:
set #pk:=0;
update
your_table
set pk=#pk:=#pk+1
order by pk;
add a column that will speicfy that is deleted
example:
1 - deleted already
0 - not deleted
and add where deleted = 0 in your select query
primary key column 2 column3 ..... deleted
1 1
2 0
3 0
4 1
5 0
Storing an number of a record would make deletes inefficient. Instead you can rely on existing SLNO indexes you already have, that should be enough for all use cases that come up to my mind.
If you SELECT whatever ORDER BY SLNO LIMIT ... OFFSET k, then returned rows have IDs k, k+1, k+2, ...
If you want to get an id of a record knowing its SLNO:
SELECT COUNT(SLNO) FROM A WHERE SLNO <= thatnumber
If you want to get thatnumber'th record:
SELECT * FROM A ORDER BY SLNO LIMIT 1 OFFSET thatnumber
You can do by alter the table and delete primary key then again create primary key.
But why you need this. If you have use this key as foreign key in other table. Then you lost all the data.

PHP - MySQL display highest ID number

What SQL query would I use to display the newest entry?
Details:
id is the primary field. I have other fields but that are not related to when they were added.
ORDER BY SomeColumn DESC
LIMIT 1
or
use the MAX() function
Since you didn't give any details about your table it is hard to answer
SELECT * from yourTable ORDER BY `id` DESC LIMIT 1;
Another (better) way would be to have a "date_added" column (date_added TIMESTAMP DEFAULT CURRENT_TIMESTAMP) so you could order by that column descending instead. Dates are more reliable than ID-assignment.
not sure if this is what your looking for but I use mysql_insert_id() after inserting a new row
The auto incremented ID columns are not always the latest records inserted, I've remember really painful experience with this behavior. Conditions where specific, it was mysql 4.1.x at the time and there was almost 1 million records, where 1 out of 3 deleted everiday, and others re inserted in the next 24hours. It made a huge mess when I realize ordering them via ID was not ordering them by age....
Since then, I use a specific column for doing age related sorts, and populating these fields with date = NOW() at each row insert.
Of course it will work to found the latest record as you want, doing an ORDER BY date DESC LIMIT 0,1on your query
SELECT Primary_Key_Field FROM table ORDER BY Primary_Key_Field DESC LIMIT 1
Replace Primary_Key_Field and table obviously :)

Categories