在MYSQL存储过程中SELECT和UPDATE相同的行

时间:2014-06-15 08:06:36

标签: mysql select stored-procedures sql-update

我正在开发一个应用程序,我需要在{N}行中m一次读取m < N行。每次我读'm'行时,我都必须在同一个表中将其状态设置为read

例如,请考虑以下表格

+------+-------------------------+--------------------------+----------+-------+---------+------+
| 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 |
+------+-------------------------+--------------------------+----------+-------+---------+------+

我希望一次只读3 rows,一旦我读取了行,我想将这些行的inqueue状态设置为1

我可以在存储过程中使用以下查询来选择行

select * from EmailQueue where inqueue=1 LIMIT 3

在此之后如何更新相同的行并将inqueue设置为1

修改

这是我创建的存储过程,它给出了一些错误。

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

在调用

时出现以下错误

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

1 个答案:

答案 0 :(得分:0)

建议使用Transaction和“SELECT FOR UPDATE”来满足您的要求。

请参阅以下链接以获取示例:

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

更新 - 添加了QUERY示例:

示例:

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

更新** **尝试使用以下方法:

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;