I have a check-in / check-out system which writes for every check-in a new row in my table and updates the table when the person checks out (like checkedout = 1)
Now I'm making a new site that always shows the newest checked in person. I do it by polling and storing the highest ID on a variable on that page. In the polling I search for entries > the id i stored. It's working good so far.
But now I want to extend it and show either the latest checked in person OR the latest checked out person. How can I get the last "updated" row in my table?
You can add a column for ex. date_checked of type datetime and update it whenever something happens.
After that just select by that column.
use mysql function called mysqli_insert_id() which will give you last inserted primary key value of the table
try this:
SET #update_id := 0;
UPDATE some_table SET column_name = 'value', id = (SELECT #update_id := id)
WHERE some_other_column = 'blah' LIMIT 1;
SELECT #update_id;
More Click Here
Related
So, I have a table A that each time a user sends an image, a record is created storing the time it was uploaded, the username of the user and the image number out of all the images uploaded over time.
I need to make a second table B that will store the amount of images uploaded per user and the user name. I need this table B to be updated when a new entry is generated in A.
I found that a trigger function can be created, nevertheless I'm having a rough time finding an example that will suit my needs.
Does anyone know a way of doin what I want?
Just update b table with a select count of total inserted records on a from current user NEW.userid (userid is your column name or whatever name you have there, and NEW is a fixed mySql reference for the current values to be inserted):
CREATE TRIGGER img_sum AFTER INSERT ON a
FOR EACH ROW SET b.total = (SELECT COUNT(*) FROM a WHERE a.userid=NEW.userid)
WHERE b.userid = NEW.userid;
From what you have described i don't think you need a second table. You can just count the number of time a user name has occurred, and you will get the number of images that user has uploaded.
You can get the count doing something like that
SELECT COUNT(DISTINCT username) FROM table_name;
If you still need to create 2 tables, you might want to take a look at procedures and how they work.
Let's say we have 3 tables for this case:
- users(id, username, email ....),
- user_images(id, userId, image_num, date_uploaded)
- user_images_count(id, user_name, images_count)
The user_images_count is initially empty. We have to fill it up by such query:
INSERT into user_images_count(user_name, images_count)
SELECT (select username from users where ui.userId = id) as username, count(userId) as counter FROM `user_images` ui group by ui.userId;
Then, we must immediately create the trigger that will process every INSERT operation into user_images table.
CREATE TRIGGER `count_user_images` AFTER INSERT ON `user_images`
FOR EACH ROW begin
declare u_name tinytext default "";
set u_name = (select username from users where id = NEW.userId limit 1);
if(u_name != "") then
update user_images_count set images_count = images_count + 1 where user_name = u_name;
end if;
end
This two queries (user_images_count fulfillment and trigger creation must be performed in one transaction, one by one).
I've created similar triggers on my local databases. They work pretty good. )))
This is actually a form to update the team members who work for a specific client, When i deselect a member then it's status turns to 0.
I have a table with all unique records. table consists of four columns -
first column is `id` which is unique and auto_incremented.
second column is `client_id`.
third column is `member_id`. (these second and third columns together make the primary key.)
fourth column is `current` which shows the status (default is 1.).
Now i have a form which sends the values of client_id and member_id. But this forms also contains the values that are already in the table BUT NOT ALL.
I need a query which
(i) `INSERT` the values that are not already in the table,
(ii) `UPDATE` the `current` column to value `0` which are in the table but not in the form values.
here is a screenshot of my form.
If (select count(*) from yourtable where client_id = and member_id = ) > 0 THEN
update yourtable set current = 0;
ELSE
insert into yourtable (client_id,member_id,current) values (value1,value2,value3)
First of all check if the value exists in the table or not, by using a SELECT query.
Then check if the result haven't save value so it will be inserted, else show an error .
This would be a great time to create a database stored procedure that flows something like...
select user
if exists update row
else insert new row
stored procedures don't improve transaction times, but they are a great addition to any piece of software.
If this doesn't solve your problem then a database trigger might help out.
Doing a little research on this matter might open up some great ideas!
Add below logic in your SP
If (select count(*) from yourtable where client_id = <value> and member_id = <value>) > 0 THEN
update yourtable set current = 0;
ELSE
insert into yourtable (client_id,member_id,current) values (value1,value2,value3)
if you want simple solution then follow this:
*) use select with each entry in selected team.
if select returns a row
then use update sql
else
use insert sql.
In your case member_id & client_id together makes the primary key.
So , you can use sql ON DUPLICATE KEY UPDATE Syntax.
Example:
$sql="INSERT INTO table_name SET
client_id='".$clientId."',
member_id='".$member_id."',
current='".$current."'
ON DUPLICATE KEY
UPDATE
current = '".$current."'
";
In this case when member_id & client_id combination repeats , it will automatically executes update query for that particular row.
I have a number which is in this form : 2012-01 (2012 as current year) and 01 is just a the maximum value of a field in my database incremented by 1, and each year that number is reset to 0.
but if there are two users that try to do the same operation at the same time the value is the same for both and thus i get the same number inserted twice in my database .
I thought of creating a sequence but that requires a job that resets the sequence each year and i would prefer if there is a way to make a lock before i get the next number and
release it after an insert is done ?
Thanks.
CREATE UNIQUE INDEX index_name ON table_name (column_name);
or
ALTER TABLE table_name ADD CONSTRAINT constraint_name UNIQUE (column_name);
You don't specify where you store the field that is used as the counter. But maybe it is possible to use a SELECT FOR UPDATE statement.
Before you increment the value of your counter field by 1 you can lock that record by using a SELECT FOR UPDATE. Then update the counter.
Something like this, assuming the table has only 1 record:
SELECT *
FROM CounterTable
FOR UPDATE;
UPDATE CounterTable
SET Counter = Counter + 1;
COMMIT;
If one session (user) has done the SELECT FOR UPDATE and not yet committed or rolled back, the other session (user) doing a SELECT FOR UPDATE will block waiting to be able to get a lock. This prevents two users from getting the same number.
I need to get next id from table (auto_increment).
I could just use SELECT * from table ORDER BY id DESC LIMIT 1;
For example I get 50. But if we delete from table two items I will get 48 but correct one
will be 51. How get correct value even we something delete from table ?
You can only use SHOW TABLE STATUS LIKE 'tablename' to fetch the auto_increment value. A simpler solution might be: SELECT MAX(id) + 1 FROM table, but this is buggy if the last entry was deleted.
show table status like 'table_name'
next id value is in 'Auto_increment' field
SHOW TABLE STATUS LIKE 'table'
The value you want is in the Auto_increment field.
Be careful about concurrency though: by the time you get around to using this value, some other client could have inserted into the table and thus your value is out of date. It's usually best to try to not need this.
SELECT LAST_INSERT_ID() + 1;
gets the last ID used in an insert in an autoincrement column + 1
I see two solutions for the next ID:
1) Select bigger value of a column with max function. Example: select max( id ) from table;
2) Using the command SHOW STATUS LIKE and get the correct index of array. Take a look: http://dev.mysql.com/doc/refman/5.1/en/show-table-status.html
Seems to me you're creating a race condition here.
Why exactly can you not insert the row you want to insert and then use LAST_INSERT_ID() to find it's ID?
How do I get the ID of the last updated row in MySQL using PHP?
I've found an answer to this problem :)
SET #update_id := 0;
UPDATE some_table SET column_name = 'value', id = (SELECT #update_id := id)
WHERE some_other_column = 'blah' LIMIT 1;
SELECT #update_id;
EDIT by aefxx
This technique can be further expanded to retrieve the ID of every row affected by an update statement:
SET #uids := null;
UPDATE footable
SET foo = 'bar'
WHERE fooid > 5
AND ( SELECT #uids := CONCAT_WS(',', fooid, #uids) );
SELECT #uids;
This will return a string with all the IDs concatenated by a comma.
Hm, I am surprised that among the answers I do not see the easiest solution.
Suppose, item_id is an integer identity column in items table and you update rows with the following statement:
UPDATE items
SET qwe = 'qwe'
WHERE asd = 'asd';
Then, to know the latest affected row right after the statement, you should slightly update the statement into the following:
UPDATE items
SET qwe = 'qwe',
item_id=LAST_INSERT_ID(item_id)
WHERE asd = 'asd';
SELECT LAST_INSERT_ID();
If you need to update only really changed row, you would need to add a conditional update of the item_id through the LAST_INSERT_ID checking if the data is going to change in the row.
This is officially simple but remarkably counter-intuitive. If you're doing:
update users set status = 'processing' where status = 'pending'
limit 1
Change it to this:
update users set status = 'processing' where status = 'pending'
and last_insert_id(user_id)
limit 1
The addition of last_insert_id(user_id) in the where clause is telling MySQL to set its internal variable to the ID of the found row. When you pass a value to last_insert_id(expr) like this, it ends up returning that value, which in the case of IDs like here is always a positive integer and therefore always evaluates to true, never interfering with the where clause. This only works if some row was actually found, so remember to check affected rows. You can then get the ID in multiple ways.
MySQL last_insert_id()
You can generate sequences without calling LAST_INSERT_ID(), but the
utility of using the function this way is that the ID value is
maintained in the server as the last automatically generated value. It
is multi-user safe because multiple clients can issue the UPDATE
statement and get their own sequence value with the SELECT statement
(or mysql_insert_id()), without affecting or being affected by other
clients that generate their own sequence values.
MySQL mysql_insert_id()
Returns the value generated for an AUTO_INCREMENT column by the
previous INSERT or UPDATE statement. Use this function after you have
performed an INSERT statement into a table that contains an
AUTO_INCREMENT field, or have used INSERT or UPDATE to set a column
value with LAST_INSERT_ID(expr).
The reason for the differences between LAST_INSERT_ID() and
mysql_insert_id() is that LAST_INSERT_ID() is made easy to use in
scripts while mysql_insert_id() tries to provide more exact
information about what happens to the AUTO_INCREMENT column.
PHP mysqli_insert_id()
Performing an INSERT or UPDATE statement using the LAST_INSERT_ID()
function will also modify the value returned by the mysqli_insert_id()
function.
Putting it all together:
$affected_rows = DB::getAffectedRows("
update users set status = 'processing'
where status = 'pending' and last_insert_id(user_id)
limit 1"
);
if ($affected_rows) {
$user_id = DB::getInsertId();
}
(FYI that DB class is here.)
This is the same method as Salman A's answer, but here's the code you actually need to do it.
First, edit your table so that it will automatically keep track of whenever a row is modified. Remove the last line if you only want to know when a row was initially inserted.
ALTER TABLE mytable
ADD lastmodified TIMESTAMP
DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP;
Then, to find out the last updated row, you can use this code.
SELECT id FROM mytable ORDER BY lastmodified DESC LIMIT 1;
This code is all lifted from MySQL vs PostgreSQL: Adding a 'Last Modified Time' Column to a Table and MySQL Manual: Sorting Rows. I just assembled it.
Query :
$sqlQuery = "UPDATE
update_table
SET
set_name = 'value'
WHERE
where_name = 'name'
LIMIT 1;";
PHP function:
function updateAndGetId($sqlQuery)
{
mysql_query(str_replace("SET", "SET id = LAST_INSERT_ID(id),", $sqlQuery));
return mysql_insert_id();
}
It's work for me ;)
SET #uids := "";
UPDATE myf___ingtable
SET id = id
WHERE id < 5
AND ( SELECT #uids := CONCAT_WS(',', CAST(id AS CHAR CHARACTER SET utf8), #uids) );
SELECT #uids;
I had to CAST the id (dunno why)... or I cannot get the #uids content (it was a blob)
Btw many thanks for Pomyk answer!
Hey, I just needed such a trick - I solved it in a different way, maybe it'll work for you. Note this is not a scalable solution and will be very bad for large data sets.
Split your query into two parts -
first, select the ids of the rows you want to update and store them in a temporary table.
secondly, do the original update with the condition in the update statement changed to where id in temp_table.
And to ensure concurrency, you need to lock the table before this two steps and then release the lock at the end.
Again, this works for me, for a query which ends with limit 1, so I don't even use a temp table, but instead simply a variable to store the result of the first select.
I prefer this method since I know I will always update only one row, and the code is straightforward.
ID of the last updated row is the same ID that you use in the 'updateQuery' to found & update that row. So, just save(call) that ID on anyway you want.
last_insert_id() depends of the AUTO_INCREMENT, but the last updated ID not.
My solution is , first decide the "id" ( #uids ) with select command and after update this id with #uids .
SET #uids := (SELECT id FROM table WHERE some = 0 LIMIT 1);
UPDATE table SET col = 1 WHERE id = #uids;SELECT #uids;
it worked on my project.
Further more to the Above Accepted Answer
For those who were wondering about := & =
Significant difference between := and =, and that is that := works as a variable-assignment operator everywhere, while = only works that way in SET statements, and is a comparison operator everywhere else.
So SELECT #var = 1 + 1; will leave #var unchanged and return a boolean (1 or 0 depending on the current value of #var), while SELECT #var := 1 + 1; will change #var to 2, and return 2.
[Source]
If you are only doing insertions, and want one from the same session, do as per peirix's answer. If you are doing modifications, you will need to modify your database schema to store which entry was most recently updated.
If you want the id from the last modification, which may have been from a different session (i.e. not the one that was just done by the PHP code running at present, but one done in response to a different request), you can add a TIMESTAMP column to your table called last_modified (see http://dev.mysql.com/doc/refman/5.1/en/datetime.html for information), and then when you update, set last_modified=CURRENT_TIME.
Having set this, you can then use a query like:
SELECT id FROM table ORDER BY last_modified DESC LIMIT 1;
to get the most recently modified row.
No need for so long Mysql code. In PHP, query should look something like this:
$updateQuery = mysql_query("UPDATE table_name SET row='value' WHERE id='$id'") or die ('Error');
$lastUpdatedId = mysql_insert_id();