Mysql select语句仅适用于while循环中的第一次迭代,插入工作正常

时间:2014-10-01 13:00:24

标签: mysql

为什么WHILE循环中的SELECT语句只返回第一次迭代的值?
INSERT IGNORE和第二INSERT都在工作,并且正在插入等于amount的行。
如果我将amount设置为10,我只会从第一个插入的行中获得结果。但是,该过程会INSERT amount行到rand_stringsrand_strings_info表。

程序:

DROP PROCEDURE if exists test_while;
DELIMITER $$
CREATE PROCEDURE test_while(amount INT, description VARCHAR(255)) 
BEGIN
WHILE amount > 0 DO
  INSERT IGNORE INTO rand_strings(rand_string) /*WORKS EVERY ITERATION*/
  SELECT generate_rand_string();       /*function to generate a random string.*/

  SELECT * FROM rand_strings WHERE id = LAST_INSERT_ID(); /*ONLY WORKS FIRST TIME */

  INSERT INTO rand_strings_info(id, col2, col3) /*WORKS EVERY ITERATION*/
  VALUES (LAST_INSERT_ID(), now(), description);

  SET amount = amount - 1;

END WHILE;
END$$

DELIMITER ;


CALL test_while(10, 'This is the description of the string…')

RESULTS:

id | rand_string

1  | jgdlkjaht

1 个答案:

答案 0 :(得分:0)

某些界面未按预期显示所有结果,但代码正确运行。

您可以在下面的 SQL Fiddle 中看到,只显示存储过程运行时rand_strings表中的第一条记录,但在MySQL命令行上运行相同的代码结果如下:

mysql> CALL `test_while`(5, 'This is the description of the string...');
+----+------------------------------------------+
| id | rand_string                              |
+----+------------------------------------------+
|  1 | f4c77a3155d95ad1e818b1b06a62deec8e0b6754 |
+----+------------------------------------------+
1 row in set (0.00 sec)

+----+------------------------------------------+
| id | rand_string                              |
+----+------------------------------------------+
|  2 | 7cbcca49596262836f5af91643303d10b3804900 |
+----+------------------------------------------+
1 row in set (0.00 sec)

+----+------------------------------------------+
| id | rand_string                              |
+----+------------------------------------------+
|  3 | 2ba2c7276c0b66e3dcbb971b7f54af9bced578a4 |
+----+------------------------------------------+
1 row in set (0.00 sec)

+----+------------------------------------------+
| id | rand_string                              |
+----+------------------------------------------+
|  4 | d52426b19a59c515b02268347c508383873d4d73 |
+----+------------------------------------------+
1 row in set (0.00 sec)

+----+------------------------------------------+
| id | rand_string                              |
+----+------------------------------------------+
|  5 | fbc25c6204b609e8f4f4f8a33b534bff9a011e5f |
+----+------------------------------------------+
1 row in set (0.00 sec)

Query OK, 1 row affected (0.00 sec)

<强>更新

DELIMITER $$

CREATE PROCEDURE `test_while`(`amount` INT, `description` VARCHAR(255))
BEGIN
  DECLARE `_LAST_INSERT_ID`, `_first_inserted_in_this_run` INT UNSIGNED DEFAULT NULL;

  CREATE TEMPORARY TABLE IF NOT EXISTS `temp_generate_rand_string` (
    `insert_id` INT UNSIGNED PRIMARY KEY,
    `first_inserted_in_this_run` INT UNSIGNED
  ) ENGINE=MEMORY;

  WHILE `amount` > 0 DO
    INSERT IGNORE INTO `rand_strings`(`rand_string`) /*WORKS EVERY ITERATION*/
    SELECT `generate_rand_string`(); /*function to generate a random string.*/
    SET `_LAST_INSERT_ID` := LAST_INSERT_ID();

    IF (`_first_inserted_in_this_run` IS NULL) THEN
      SET `_first_inserted_in_this_run` := `_LAST_INSERT_ID`;
    END IF;

    INSERT INTO `temp_generate_rand_string` (`insert_id`, `first_inserted_in_this_run`)
    VALUES
    (`_LAST_INSERT_ID`, `_first_inserted_in_this_run`);

    -- SELECT * FROM `rand_strings` WHERE `id` = `_LAST_INSERT_ID`; /*ONLY WORKS FIRST TIME */

    INSERT INTO `rand_strings_info`(`id`, `col2`, `col3`) /*WORKS EVERY ITERATION*/
    VALUES (`_LAST_INSERT_ID`, NOW(), `description`);

    SET `amount` := `amount` - 1;
  END WHILE;

  SELECT `rs`.`id`, `rs`.`rand_string`
  FROM `rand_strings` `rs`
    INNER JOIN `temp_generate_rand_string` `tgrs` ON
     `tgrs`.`first_inserted_in_this_run` = `_first_inserted_in_this_run` AND
     `rs`.`id` = `tgrs`.`insert_id`;

  DELETE
  FROM `temp_generate_rand_string`
  WHERE `first_inserted_in_this_run` = `_first_inserted_in_this_run`;
END$$

DELIMITER ;

SQL Fiddle demo