Цикл пока в хранимой процедуре - PullRequest
0 голосов
/ 29 октября 2009

Я пытаюсь написать процедуру, которая будет запускать один и тот же запрос выбора до тех пор, пока число результатов не станет больше 0. Если «интервал 2 часа» возвращает 0 записей, тогда следует использовать критерий «интервал 4 часа», и если еще нет записей, тогда lastupdate> current_date () следует использовать в предложении where.

Это 2 основных запроса, используемых в процедуре.

select sql_calc_found_rows id from sometable where lastupdate > date_sub(now(), interval 2 hour) limit 10;

select found_rows();
+--------------+
| found_rows() |
+--------------+
|           41 | 
+--------------+

Правильна ли следующая процедура? Это правильный способ написать SP? И как мне использовать результаты в коде PHP?

delimiter $$
create procedure mytest3()
begin 

  declare myvar int;

 select sql_calc_found_rows id 
   from sometable 
  where lastupdate > date_sub(now(), interval 2 hour) 
  limit 10;

 select found_rows() into myvar;

if (myvar > 0) 
  then select 'Found in 2 hours';
else
  select sql_calc_found_rows id 
    from sometable 
   where lastupdate > date_sub(now(), interval 4 hour) 
   limit 10;

select found_rows() into myvar;

if (myvar > 0) 
  then select 'Found in 4 hours';
else 
  select sql_calc_found_rows id 
    from sometable 
   where lastupdate > current_date() 
   limit 10;
end if;
end if; 
end$$ 

Ответы [ 5 ]

5 голосов
/ 07 ноября 2009

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

Вот один из способов достижения этого:

delimiter $$
create procedure recently_modified_rows()
begin 

  declare tablelastupdate int; -- how many hours ago table was last updated.
  declare showperiod datetime; -- what time interval to show
  declare showtext  text;      -- text describing time interval

  select hour(timediff(now(), max(lastupdate))) into tablelastupdate
    from sometable;

  if(tablelastupdate < 2)
     set showperiod = time_sub(now(), interval 2 hours);
     set showtext = "modified in the last 2 hours";
  elseif (tablelastupdate < 4)
     set showperiod = time_sub(now(), interval 4 hours);
     set showtext = "modified in the last 4 hours";
  else
     set showperiod = current_date();
     set showtext = "modified today";
  end if

  select sql_calc_found_rows id, 
         showtext description
     from sometable 
     where lastupdate > showperiod 
     limit 10;

end$$

и вызывать его с php:

$query = mysql_query("call recently_modified_rows()") or die( mysql_error() );
$numrows = mysql_numrows($query);

if ($numrows != 0)
{
    /* print out what time interval we used */
    $description = mysql_result($query, 0, 'description');
    echo "Found $numrows rows $description";

    /* print out the rows */
    while ($row = mysql_fetch_array($query)) 
    {
       echo "Id: {$row['id']}";
    }

}
else 
{
    /* happens only if there were no records modified in any of the three versions */
    echo "no records were modified in the last 2 hours, 4 hours, or today";
}
4 голосов
/ 05 ноября 2009

В зависимости от вашей ситуации, может быть лучше настроить триггер (http://dev.mysql.com/doc/refman/5.0/en/triggers.html) для вашей базы данных. Это позволяет выполнять любую необходимую работу / пересчеты только при изменении соответствующих данных, вместо того, чтобы чрезмерно загружать сервер непрерывным опросом, даже если ничего в базе данных не изменилось.

2 голосов
/ 07 ноября 2009

Это моя первая попытка опубликовать ответ в StackOverflow. Надеюсь, что это полезно ..

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

Функция Sleep предназначена для того, чтобы не дать процедуре съесть слишком много ЦП, пока она работает, запуская Select Count (*) только один раз в секунду. Вы можете установить это на любой интервал, который вы хотите.

Хотя эта процедура работает хорошо, я должен согласиться с natevw об использовании Триггеров .

 DELIMITER $$

 CREATE PROCEDURE sp_TestQueryResultsTimeout()
 BEGIN


   DECLARE v_interval, ct, v_time INT;

   /* This will keep track of how much time has passed*/
   SET v_interval = 0;

   /* This is used for comparing the rowcount*/
   SET ct = 0;

   /* This is used to keep the procedure from returning the Sleep functions results'
      This could also be used to keep a more accurate count of the amount of Sleep time has passed by adding the results of the sleep function to it on every iteration*/
   SET v_time = 0;

   /* This while statement should run for slightly longer than ten seconds
      The amount of extra time will begin to add up depending on how long the select count (*) takes
      and how many iterations you want to make'*/

   WHILE v_interval < 10 DO

   /*Get the count from your table*/
       SET ct = (SELECT count(*) FROM tbUsers);

     /*If the count is greater than 0, exit the while by satisfying the condition*/
   if (ct > 0) then
    SET v_interval = 10;
   else
    /*If the count is less than 0, sleep for 1 second*/
         SET v_time = (SELECT SLEEP(1));
   end if;

       /*Increment*/
       SET v_interval = v_interval + 1;
   END WHILE;

   SELECT * FROM tbUsers;

 END$$

 DELIMITER ;
0 голосов
/ 04 ноября 2009

PHP-страницы будут запускаться пользователями, так что вам придется сохранять результат в базе данных, пока кто-то не откроет эту страницу, на которой отображается результат.

Вместо использования бесконечного цикла в вашей базе данных, вы можете использовать cronjob PHP.

0 голосов
/ 29 октября 2009

Из документов MySQL:

CREATE PROCEDURE dowhile()
BEGIN
  DECLARE v1 INT DEFAULT 5;

  WHILE v1 > 0 DO
    ...
    SET v1 = v1 - 1;
  END WHILE;
END
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...