MySQL在存储过程中递增变量

标签 mysql stored-procedures

所以我有一个例程(伪代码):

$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/

相关文章:

Oracle存储过程-根据可选参数动态生成选择语句

MySQL Window函数计算百分比

mysql - 列名中包含数字分数的 SELECT 列时出错 --mysql

asp.net - 在 SELECT 子句中显示不同 COUNT 的存储过程

sql - 如何从 1 行获取查询值以用于另一行?

oracle - 每次 EXECUTE IMMEDIATE 后都需要 COMMIT 吗?

sql - 在 SQL Server 2008 中使用 xml 和存储过程将数据插入到表中

PHP/MySQL - 根据表 2 中的计数从表 1 中获取结果

java - 使用 connection.createStatement().executeQuery(String query); 是否安全?

java - 如何在 hibernate 中使用 DitachedCriteria 对名称列表 <User> 进行排序?