直到存储过程中的循环

时间:2009-10-29 06:40:13

标签: php sql mysql

我正在尝试编写一个过程,该过程将触发相同的选择查询,直到结果数大于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 个答案:

答案 0 :(得分:5)

在我看来,当你要求在文本的标题和正文中都有一个循环时,你真正要做的就是获取“在过去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";
}

答案 1 :(得分:4)

根据您的具体情况,最好在数据库上设置触发器(http://dev.mysql.com/doc/refman/5.0/en/triggers.html)。这使您可以仅在相关数据更改时执行任何必要的工作/重新计算,而不是通过持续轮询使服务器不必要地繁忙,即使数据库中没有任何更改也是如此。

答案 2 :(得分:2)

这是我第一次尝试在StackOverflow上发布答案。希望它有用..

我在下面使用我的本地MySQL数据库编写了一个测试程序。如果没有记录,它将设置为运行10整秒并返回空结果集。如果在它运行的十秒内插入一行,它将退出循环并返回新结果。

睡眠功能用于防止程序在运行时因每秒只运行一次选择计数(*)而占用太多CPU。您可以将其设置为您想要的任何间隔。

虽然此程序运作良好,但我必须同意 natevw 使用Triggers

 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 ;

答案 3 :(得分:0)

来自MySQL文档:

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

  WHILE v1 > 0 DO
    ...
    SET v1 = v1 - 1;
  END WHILE;
END

答案 4 :(得分:0)

PHP页面将由用户触发,因此您必须将结果保存到数据库中,直到有人打开该页面(显示结果)。

您可以使用PHP cronjob,而不是在数据库中使用无限循环。