所以我有一个例程(伪代码):
$rows = SELECT DISTINCT a, b FROM t1;
foreach($rows as $row) {
SET @i = 0;
UPDATE t1 SET c_index = @i := (@i+1)
WHERE a = $row[a] and b = $row[b] ORDER BY c DESC;
}
重点是按照行的排序方式对行子集进行编号。工作正常,但更新运行了数千次,所以速度相当慢。为了加快速度,我想将其放入存储过程中。
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE vA, vB, i INT;
DECLARE cur1 CURSOR FOR
SELECT DISTINCT a, b
FROM t1 WHERE ...;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN cur1;
WHILE done = 0 DO
FETCH cur1 INTO vA, vB;
IF done = 0 THEN
SET i=0;
UPDATE t1
SET c_index = i:= (i+1)
WHERE a = vA AND b = vB
ORDER BY c DESC;
END IF;
END WHILE;
CLOSE cur1;
END
但是,当创建上述过程时,MySQL 表示“i := ...”处存在语法错误。如果我对“i”使用 session 变量,它就可以工作(@i)。在存储过程中使用 session 变量不是很优雅。如何在不使用“i” session 变量的情况下修复上述存储过程?
最佳答案
已更新:由于 MySQL 游标不可更新(只读),因此在您的情况下使用游标没有多大意义。几乎您能想到的所有内容都可以通过纯 UPDATE
语句来表达。
如果(a, b, c)
是唯一的,你可以这样做
UPDATE table1 t JOIN
(
SELECT a, b, c,
(
SELECT 1 + COUNT(*)
FROM table1
WHERE a = t.a
AND b = t.b
AND c > t.c
) rnum
FROM table1 t
) s
ON t.a = s.a
AND t.b = s.b
AND t.c = s.c
SET t.c_index = s.rnum
这里是SQLFiddle 演示
或者如果您碰巧有某种id
(例如auto_increment
列),那么
UPDATE table1 t JOIN
(
SELECT id,
(
SELECT 1 + COUNT(*)
FROM table1
WHERE a = t.a
AND b = t.b
AND c > t.c
) rnum
FROM table1 t
) s
ON t.id = s.id
SET t.c_index = s.rnum
这里是SQLFiddle 演示
关于MySQL在存储过程中递增变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19917715/