This may seem like a repeat question, but it always seems to be questions involving more than one table. When a row in a table is selected, I will also need to +1 the view count in the same row. I know I can't use a trigger or two statements in the same query, but could both of these things be done with a single connection to the database? What would the preferred method be to both select a row and then +1 the view field?
It can be done in the same connection, but I can't think of a way for that to be done using one query.
Here is how you would do that in a single transaction;
START TRANSACTION;
UPDATE tbl SET view=view+1 WHERE id = 10;
SELECT * FROM tbl WHERE id = 10;
COMMIT;
A second "better" method you can do that which eliminates having to read the tbl table twice.
UPDATE tbl
SET view = (#viewsCount := view + 1)
WHERE id = 10;
And to get the new value of the views count I would do something like this
SELECT #viewsCount;
A third way would be by utilizing the LAST_INSERT_ID() function like so
UPDATE tbl
SET view = LAST_INSERT_ID(view) + 1
WHERE id = 10;
Then to get the new view count you will need to execute this query immediately after the update. you can not execute any other queries after the update otherwise you will not get the intended value.
SELECT LAST_INSERT_ID();
Related
I need to lock rows in the same moment as it's been selected.
So I need some kind of transaction that will:
1) SELECT * FROM changes WHERE locked=0
2) UPDATE changes SET locked=1
3) return 1st query result
Is it possible?
you can mix all queries together so you can get the final result as you want, you will need to sign the date of the change to be able to sort and filtering for the last change:
transact SQL:
string sql = "update changes set locked = 1, changed_date = getdate() where locked = 0;select top 1 * from changes order by changed_date desc;";
DataTable tbl = dal.fillAdapter();
or call Stored Procedure holding the same queries, you can execute scalar to check if any row affected because the update and only if changes happens you will query for the last changes, in other words endless combinations to solved this problem.
Based on what you have clarified, transactions will be your best bet (docs).
START TRANSACTION;
/* Select the records to be changed */
SELECT * FROM changes WHERE locked=0;
/* Update records to set those that are not locked to locked */
UPDATE changes SET locked=1 WHERE locked = 0;
COMMIT;
Update table set Style='new' where id=(SELECT MAX(id) From table);
This is my query. But not working in mysql.
Error shows: You can't specify target table 'table' for update in FROM clause
Please help.
You can store the result of the subquery in a session variable, like so:
SELECT MAX(id) INTO #maxID
FROM table
;
UPDATE table
SET Style='new'
WHERE id=#maxID
;
Note that the operation is no longer "atomic"; depending on the activity going on, it is potentially possible for that MAX(id) to change between the SELECT and the UPDATE.
Another possibility is:
UPDATE table
SET Style = 'new'
ORDER BY id DESC
LIMIT 1
;
But I tend to (for no particular reason) be averse to such queries.
In MySQL, is it possible to update the selected records on the same query?
For eg., If the query
SELECT *
FROM `table`
WHERE field = "value"
LIMIT 0,2
Return two rows, then on the same query, i need to increment the table's count field by 1. Is it possible?
Yes its possible you can write as UPDATE query as:
UPDATE my_table
SET count = count + 1
WHERE field = "value"
LIMIT 2;
or for LIMIT with offset try:
UPDATE my_table a
INNER JOIN (SELECT id FROM my_table WHERE field = "value" LIMIT 0, 2) b
ON a.id = b.id
SET count = count + 1;
It's not possible. The verb SELECT only retrieves data (without modifying it); and the verb UPDATE only modifies data (without retrieving it). There is no MySQL verb that will perform both actions. You will have to use two separate statements.
However, those two statements can be encapsulated within a transaction (if supported by your storage engine) to ensure that they are conducted atomically and/or could be invoked from within a stored procedure to simplify the command that must be issued by your client. Combining the two one would have:
DELIMITER ;;
CREATE PROCEDURE select_and_update(value TEXT)
BEGIN
START TRANSACTION;
SELECT * FROM `table` WHERE field = value LIMIT 0,2;
UPDATE `table` SET count = count + 1 WHERE ...;
COMMIT;
END;;
DELIMITER ;
Then your client need merely do:
CALL select_and_update('value');
I am trying to combine these two queries in twisted python:
SELECT * FROM table WHERE group_id = 1013 and time > 100;
and:
UPDATE table SET time = 0 WHERE group_id = 1013 and time > 100
into a single query. Is it possible to do so?
I tried putting the SELECT in a sub query, but I don't think the whole query returns me what I want.
Is there a way to do this? (even better, without a sub query)
Or do I just have to stick with two queries?
Thank You,
Quan
Apparently mysql does have something that might be of use, especially if you are only updating one row.
This example is from: http://lists.mysql.com/mysql/219882
UPDATE mytable SET
mycolumn = #mycolumn := mycolumn + 1
WHERE mykey = 'dante';
SELECT #mycolumn;
I've never tried this though, but do let me know how you get on.
This is really late to the party, but I had this same problem, and the solution I found most helpful was the following:
SET #uids := null;
UPDATE footable
SET foo = 'bar'
WHERE fooid > 5
AND ( SELECT #uids := CONCAT_WS(',', fooid, #uids) );
SELECT #uids;
from https://gist.github.com/PieterScheffers/189cad9510d304118c33135965e9cddb
You can't combine these queries directly. But you can write a stored procedure that executes both queries. example:
delimiter |
create procedure upd_select(IN group INT, IN time INT)
begin
UPDATE table SET time = 0 WHERE group_id = #group and time > #time;
SELECT * FROM table WHERE group_id = #group and time > #time;
end;
|
delimiter ;
So what you're trying to do is reset time to zero whenever you access a row -- sort of like a trigger, but MySQL cannot do triggers after SELECT.
Probably the best way to do it with one server request from the app is to write a stored procedure that updates and then returns the row. If it's very important to have the two occur together, wrap the two statements in a transaction.
There is a faster version of the return of updated rows, and more correct when dealing with highly loaded system asks for the execution of the query at the same time on the same database server
update table_name WITH (UPDLOCK, READPAST)
SET state = 1
OUTPUT inserted.
UPDATE tab SET column=value RETURNING column1,column2...
Is there a way in SQL (MySQL) to increment a value, and also return the value in a single query. I am trying to ovoid doing two queries like the following:
QUERY 1
UPDATE my_table SET my_col = (my_col + 1) WHERE something = something_else;
QUERY 2
SELECT my_col FROM my_table WHERE something = something_else;
Thanks.
To my knowledge there is still no such possibility in MySQL, but take a look at this question for a possible workaround that at least lets you have the select and update work with the same data transactionally.
There is no way to make a select and a update at the same time.
If you want to avoid the select you can declare a variable and put there the value, but that will put the last updated row value in the variable.
declare #value int
UPDATE my_table SET my_col = (my_col + 1), #value = (my_col + 1) WHERE something = something_else;
I don't know what scripting language you are using but here is an example on creating a stored procedure in MySQL that returns the updated value so you can update and select in one operation:
Get Updated Value in MySQL instead of affected rows