简体   繁体   English

使用 SELECT 的结果集...用于更新 MySQL 存储过程

[英]Use ResultSet of SELECT...FOR UPDATE in MySQL Stored Procedure

I'm using MySql 5.7 trying to create a stored procedure that will update a set of rows in a transaction and return the rows that were updated.我正在使用 MySql 5.7 尝试创建一个存储过程,该过程将更新事务中的一组行并返回已更新的行。 After creating the locks, I then update those rows, but can't figure out how to use the ids returned from the SELECT...FOR UPDATE statement.创建锁后,我会更新这些行,但无法弄清楚如何使用从SELECT...FOR UPDATE语句返回的 ID。 Instead I have to scan the table again in the update statement looking for the rows I just locked.相反,我必须在更新语句中再次扫描表以查找我刚刚锁定的行。 Here's an example of my procedure.这是我的程序的一个例子。

DELIMITER //
CREATE PROCEDURE cleanUp()
BEGIN
        START TRANSACTION;

        SELECT * FROM t WHERE t.state = 'foobar' AND t.value < 10 FOR UPDATE;

        UPDATE t SET t.state = 'fizzbuzz' WHERE t.state = 'foobar' AND t.value < 10;

        COMMIT;
END //

I'd prefer to not have to scan the table twice for t.state = 'foobar' AND t.value < 10 .我宁愿不必为t.state = 'foobar' AND t.value < 10扫描两次表。 I'd also like to guarantee that I only update the rows I just locked, not other rows that might have been changed to meet that criteria mid-transaction.我还想保证我更新我刚刚锁定的行,而不更新可能已更改以满足交易中的标准的其他行。

Is there a way to use the results of SELECT..FOR UPDATE in the UPDATE statement so I can update rows by id instead?有没有办法在UPDATE语句中使用SELECT..FOR UPDATE的结果,这样我就可以通过 id 更新行?

Note: I've tried loading the results into a temp table and using a cursor and both do not work.注意:我已尝试将结果加载到临时表中并使用 cursor,但两者均无效。

MySQL can't declared variable as table, so you need o write the select in a FROM clause, which can for example do as IN clause like the query below MySQL 不能将变量声明为表,因此您需要将 select 写在 FROM 子句中,例如可以像下面的查询一样执行 IN 子句

CREATE TABLe t(id int, state varchar(10), value int)
 INSERT INTO t VALUEs(1,'foobar',1),(2,'foobar',1),(3,'foobar',1)
 CREATE PROCEDURE cleanUp() BEGIN START TRANSACTION; UPDATE t SET t.state = 'fizzbuzz' WHERE id IN (SELECT id FROM (SELECT id FROM t WHERE t.state = 'foobar' AND t.value < 10 FOR UPDATE) t1 ); COMMIT; END
 CALL cleanUp()
 SELECT * FROM t
 id |编号 | state | state | value -: |:------- |值 -: |:------ | ----: 1 | ----: 1 | fizzbuzz |嘶嘶声 | 1 2 | 1 2 | fizzbuzz |嘶嘶声 | 1 3 | 1 3 | fizzbuzz |嘶嘶声 | 1 1个

db<>fiddle here db<> 在这里摆弄

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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