Как я могу пройти по всем строкам таблицы?(Баз данных) - PullRequest
65 голосов
/ 28 апреля 2011

У меня есть таблица A и один идентификатор первичного ключа.

Теперь я хочу просмотреть все строки в A.

Я нашел что-то вроде «для каждой записи в A», но, похоже, это не то, как вы делаете это в MySQL.

Дело в том, что для каждой строки я хочу взять поле и преобразовать его, вставить в другую таблицу и затем обновить некоторые поля строки.Я могу поместить часть выбора и вставку в одно утверждение, но я не знаю, как получить обновление там же.Так что я хочу зациклить.И для практики я не хочу использовать ничего, кроме MySQL.

edit

Буду признателен за пример.

И решение, котороене нужно вводить в процедуру.

edit 2

хорошо, подумайте об этом сценарии:

Таблица A и B, каждая с полямиID и VAL.

Теперь это псевдокод того, что я хочу сделать:

for(each row in A as rowA)
{
  insert into B(ID, VAL) values(rowA[ID], rowA[VAL]);
}

, в основном копирование содержимого A в B с использованием цикла.

(это просто упрощенный пример, конечно, для этого вы бы не использовали цикл.)}

Ответы [ 5 ]

99 голосов
/ 03 мая 2013

Поскольку предложение цикла подразумевает запрос решения типа процедуры.Вот мое.

Любой запрос, который работает с любой отдельной записью, взятой из таблицы, может быть заключен в процедуру, чтобы он выполнялся через каждую строку таблицы следующим образом:

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;
;;

Затем не забудьте сбросить разделитель

DELIMITER ;

и запустить новую процедуру

CALL ROWPERROW();

Вы можете делать все, что захотите, в строке «INSERT INTO», которую я просто скопировал из вашего примера запроса.

ВНИМАТЕЛЬНО обратите внимание, что используемая здесь строка «INSERT INTO» отражает строку в вопросе.,Согласно комментариям к этому ответу, вы должны убедиться, что ваш запрос синтаксически корректен для любой версии SQL, которую вы используете.

В простом случае, когда поле идентификатора увеличивается и начинается с 1 строки вПримером может быть:

INSERT INTO table_B(ID, VAL) VALUES(ID, VAL) FROM table_A WHERE ID=i;

Замена строки «SELECT COUNT» на

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;
;;

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

Я советую выполнять запросы на основе набора, когда это возможно, и толькоиспользуйте простые циклы или курсоры, если вам нужно.

12 голосов
/ 28 апреля 2011

Вы действительно должны использовать решение на основе множеств, включающее два запроса (базовая вставка):

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

Теперь, если преобразование более сложное, чемчтобы и включало несколько таблиц, опубликуйте еще один вопрос с подробностями.

4 голосов
/ 28 апреля 2011

КУРСОРЫ - вариант здесь, но, как правило, его осуждают, поскольку они часто не наилучшим образом используют механизм запросов. Подумайте о том, чтобы исследовать «SET Based Queries», чтобы увидеть, можете ли вы достичь того, что вы хотите делать, без использования CURSOR.

0 голосов
/ 13 сентября 2018

Пример мистера Пурпала, который я использовал в триггере 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
0 голосов
/ 23 августа 2016
    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
    }   
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...