2013-11-11 5 views
0

Таким образом, у меня есть процедура, которая делает (псевдо-код):MySQL приращения переменного в хранимой процедуре

$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», она работает (@i). Использование переменной сеанса в хранимой процедуре не очень элегантно. Как можно сохранить указанную выше хранимую процедуру без использования переменной сеанса для «i»?

ответ

1

ОБНОВЛЕНО: Поскольку курсоры 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 demo

+0

Нет, приращение в первую очередь не помогает, так как для каждой строки требуется увеличение, а ваше окончательное решение использует переменные сеанса, которых я хочу избежать. – ColinM

+0

@ColinM у вас есть какой-то «идентификатор» в вашей таблице (например, колонка автоинкремента)? – peterm

+0

@ColinM или это комбинация '(a, b, c)' UNIQUE? – peterm

Смежные вопросы