简体   繁体   中英

SELECT and UPDATE same rows in MYSQL stored procedure

I'm working on a application for which I need to read m rows at a time out of total 'N' rows where m < N . Every time I read 'm' rows I have to set their status as read in the same table.

For example consider following table

+------+-------------------------+--------------------------+----------+-------+---------+------+
| ID   | from_email_address      | to_email_address         | subject  | body  | inqueue | sent |
+------+-------------------------+--------------------------+----------+-------+---------+------+
|    1 | 0120sushil@gmail.com    | kumar.sushil@outlook.com | Subject1 | Body1 |            0 |    0 |
|    2 | 0120ksushil@gmail.com   | kumar.sushil@outlook.com | Subject1 | Body1 |          0 |    0 |
|    3 | shivaseth1@gmail.com    | kumar.sushil@outlook.com | Subject1 | Body1 |       0     |    0 |
|    4 | shivaseth1@gmail.com    | amanrajg@outlook.com     | Subject1 | Body1 |       0     |    0 |
|    5 | shivamprakash@gmail.com | amanrajg@outlook.com     | Subject1 | Body1 |           0 |    0 |
|    6 | shivamprakash@gmail.com | poorvanagpal@outlook.com | Subject1 | Body1 |       0 |    0 |
|    7 | shivankgupta@gmail.com  | poorvanagpal@outlook.com | Subject1 | Body1 |       0 |    0 |
+------+-------------------------+--------------------------+----------+-------+---------+------+

I want to read lets say 3 rows at a time and once I have read the rows I want to set inqueue status of those rows as 1 .

I can use following query in stored procedure to select the rows

select * from EmailQueue where inqueue=1 LIMIT 3

After this how to update the same rows and set their inqueue to 1 .

EDIT

Here is the stored procedure I created which is giving some error.

DELIMITER $$
DROP PROCEDURE IF EXISTS GetUnsentMails;
CREATE PROCEDURE GetUnsentMails()
BEGIN
START TRANSACTION;
    CREATE TEMPORARY TABLE temp_EmailQueue AS SELECT * FROM EmailQueue WHERE inqueue = 0 LIMIT 5 FOR UPDATE;
    UPDATE EmailQueue SET inqueue=1 where id in (SELECT id from temp_EmailQueue) AND inqueue = 0;
COMMIT;
END

It gives following error on calling

ERROR 1746 (HY000): Can't update table 'emailqueue' while 'temp_EmailQueue' is being created.

Suggesting to use Transaction and "SELECT FOR UPDATE" to fulfill your requirements.

Please refer following links for the examples:

MySQL 'select for update' behaviour

http://dev.mysql.com/doc/refman/5.0/en/innodb-locking-reads.html

http://www.sqlines.com/mysql/how-to/select-update-single-statement-race-condition

UPDATE - Added the QUERY EXAMPLE:

Example:

.......
#Before starting procedure
.......
START TRANSACTION;
CREATE TEMPORARY TABLE zzz_EmailQueue AS SELECT * FROM EmailQueue WHERE inqueue=1 LIMIT 3 FOR UPDATE;
.....
.....
#Section for other activities....
.....
.....
UPDATE EmailQueue SET inqueue=<<New_Value>> WHERE id IN (SELECT id FROM zzz_EmailQueue) AND inqueue=1;
COMMIT;
.......
#Remaining lines of Prodecure
.......

Update ** **Try with following method:

DECLARE v_EmailQueue_ID DOUBLE;
SELECT ID INTO v_EmailQueue_ID FROM EmailQueue WHERE inqueue = 0 LIMIT 1 FOR UPDATE;
UPDATE EmailQueue SET inqueue=1 WHERE id=v_EmailQueue_ID AND inqueue = 0;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM