У меня есть таблица A и один идентификатор первичного ключа.
Теперь я хочу пройти все строки в A.
Я нашел что-то вроде «для каждой записи в A», но, похоже, это не так, как в MySQL.
Дело в том, что для каждой строки я хочу взять поле и преобразовать его, вставить в другую таблицу, а затем обновить некоторые поля строки. Я могу поместить выделенную часть и вставку в один оператор, но я также не знаю, как получить там обновление. Итак, я хочу зациклить. И для практики я не хочу использовать ничего, кроме MySQL.
редактировать
Буду признателен за пример.
И решение, которое не нужно вводить в процедуру.
редактировать 2
хорошо подумайте об этом сценарии:
Таблицы A и B, каждая с полями ID и VAL.
Это псевдокод того, что я хочу сделать:
for(each row in A as rowA)
{
insert into B(ID, VAL) values(rowA[ID], rowA[VAL]);
}
в основном копирование содержимого A в B с помощью цикла.
(это просто упрощенный пример, конечно, вы бы не использовали для этого цикл.)}
Ответы:
Поскольку предложение цикла подразумевает запрос решения типа процедуры. Вот мой.
Любой запрос, который работает с любой отдельной записью, взятой из таблицы, можно обернуть в процедуру, чтобы он проходил через каждую строку таблицы следующим образом:
DROP PROCEDURE IF EXISTS ROWPERROW; DELIMITER ;;
Тогда вот процедура в соответствии с вашим примером (table_A и table_B используются для ясности)
CREATE PROCEDURE ROWPERROW() BEGIN DECLARE n INT DEFAULT 0; DECLARE i INT DEFAULT 0; SELECT COUNT(*) FROM table_A INTO n; SET i=0; WHILE i<n DO INSERT INTO table_B(ID, VAL) SELECT (ID, VAL) FROM table_A LIMIT i,1; SET i = i + 1; END WHILE; End; ;;
Тогда не забудьте сбросить разделитель
И запускаем новую процедуру
CALL ROWPERROW();
Вы можете делать все, что хотите, в строке «INSERT INTO», которую я просто скопировал из вашего примера запроса.
ВНИМАТЕЛЬНО обратите внимание на то, что использованная здесь строка «INSERT INTO» отражает строку в вопросе. В соответствии с комментариями к этому ответу вам необходимо убедиться, что ваш запрос синтаксически верен для какой-либо версии SQL, которую вы используете.
В простом случае, когда поле вашего идентификатора увеличивается и начинается с 1, строка в примере может выглядеть так:
INSERT INTO table_B(ID, VAL) VALUES(ID, VAL) FROM table_A WHERE ID=i;
Замена строки «ВЫБРАТЬ СЧЕТЧИК» на
SET n=10;
Позволит вам протестировать ваш запрос только на первых 10 записях в table_A.
Последняя вещь. Этот процесс также очень легко вложить в разные таблицы, и это был единственный способ выполнить процесс для одной таблицы, который динамически вставлял разное количество записей в новую таблицу из каждой строки родительской таблицы.
Если вам нужно, чтобы он работал быстрее, обязательно попробуйте настроить его на основе, если нет, тогда это нормально. Вы также можете переписать приведенное выше в форме курсора, но это не может улучшить производительность. например:
DROP PROCEDURE IF EXISTS cursor_ROWPERROW; DELIMITER ;; CREATE PROCEDURE cursor_ROWPERROW() BEGIN DECLARE cursor_ID INT; DECLARE cursor_VAL VARCHAR; DECLARE done INT DEFAULT FALSE; DECLARE cursor_i CURSOR FOR SELECT ID,VAL FROM table_A; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; OPEN cursor_i; read_loop: LOOP FETCH cursor_i INTO cursor_ID, cursor_VAL; IF done THEN LEAVE read_loop; END IF; INSERT INTO table_B(ID, VAL) VALUES(cursor_ID, cursor_VAL); END LOOP; CLOSE cursor_i; END; ;;
Не забудьте объявить переменные, которые вы будете использовать, того же типа, что и переменные из запрашиваемых таблиц.
Я советую использовать запросы на основе наборов, когда это возможно, и использовать только простые циклы или курсоры, если это необходимо.
источник
LIMIT i,1000;
иset i = i + 1000
;Вам действительно следует использовать решение на основе набора, включающее два запроса (базовая вставка):
INSERT INTO TableB (Id2Column, Column33, Column44) SELECT id, column1, column2 FROM TableA UPDATE TableA SET column1 = column2 * column3
И для вашего преобразования:
INSERT INTO TableB (Id2Column, Column33, Column44) SELECT id, column1 * column4 * 100, (column2 / column12) FROM TableA UPDATE TableA SET column1 = column2 * column3
Теперь, если ваше преобразование более сложное и включает несколько таблиц, опубликуйте еще один вопрос с подробностями.
источник
КУРСОРЫ являются здесь вариантом, но обычно не одобряются, так как они часто не наилучшим образом используют механизм запросов. Подумайте о том, чтобы изучить «Запросы на основе SET», чтобы увидеть, сможете ли вы достичь того, чего хотите, без использования КУРСОРА.
источник
Пример мистера Purple, который я использовал в триггере mysql, например,
begin DECLARE n INT DEFAULT 0; DECLARE i INT DEFAULT 0; Select COUNT(*) from user where deleted_at is null INTO n; SET i=0; WHILE i<n DO INSERT INTO user_notification(notification_id,status,userId)values(new.notification_id,1,(Select userId FROM user LIMIT i,1)) ; SET i = i + 1; END WHILE; end
источник
Use this: $stmt = $user->runQuery("SELECT * FROM tbl WHERE ID=:id"); $stmt->bindparam(":id",$id); $stmt->execute(); $stmt->bindColumn("a_b",$xx); $stmt->bindColumn("c_d",$yy); while($rows = $stmt->fetch(PDO::FETCH_BOUND)) { //---insert into new tble }
источник