查询 运行 无穷无尽(嵌套 cursor/loop)- MySQL

Query running endless (Nested cursor/loop) - MySQL

我已经写了这个查询,但可能存在一些我找不到的逻辑错误。游标或游标内的循环永远是 运行,一段时间后我得到最大结果数达到错误。

提前致谢。

    CREATE DEFINER=`root`@`localhost` PROCEDURE `sp_update_productsearch_datasync`()
BEGIN

  DECLARE p_searchtext longtext default ''; 
  DECLARE p_broken_str VARCHAR(1000) default ''; 
  DECLARE p_alternative_str VARCHAR(1000) default ''; 
  DECLARE p_item int(11) default 0; 
  DECLARE search_loop_finished, alternative_search_loop_finished boolean default false; 

  DECLARE srchbox_cur CURSOR FOR SELECT DISTINCT item, searchbox 
  FROM  productsearch where searchbox is not null limit 10; 

  DECLARE continue HANDLER for NOT found SET search_loop_finished = true; 

  OPEN srchbox_cur;   
  srchbox_loop : loop   
  FETCH srchbox_cur INTO  p_item,p_searchtext; 

    set p_searchtext = replace(p_searchtext,' ','|'); 

    IF search_loop_finished then 
        close srchbox_cur;
        leave srchbox_loop; 
    END IF; 


    drop TABLE IF EXISTS split_vals;      
    create temporary TABLE split_vals(vals varchar(1000));  

      begin_block1: begin 
        DECLARE loop_idx  int DEFAULT 0; 
        declare idx       int DEFAULT 0; 
        declare start_idx int DEFAULT 1; 
        declare str       varchar(500); 
        declare cc        varchar(1); 

        split_val_loop : loop 
                SET loop_idx = loop_idx+1; 
                set idx=idx+1; 
                set str = substr(p_searchtext,start_idx,idx); 
                set cc = substr(p_searchtext,(start_idx+idx),1); 

                if cc = '|' THEN 
                    SET idx=idx+1; 
                    set start_idx = idx + start_idx; 
                    set idx=0; 
                    insert INTO split_vals VALUES (str ); 

                    set str = ''; 
                    set cc = ''; 
                elseif loop_idx = length(p_searchtext) THEN 
                    insert INTO split_vals VALUES (str); 

                leave split_val_loop; 
                end IF; 
            end LOOP split_val_loop;
        END begin_block1;

-- select * from split_vals;


    begin_block2 : Begin

      DECLARE alternative_search_cur CURSOR FOR SELECT DISTINCT vals FROM  split_vals; 

      DECLARE continue HANDLER for NOT found SET  alternative_search_loop_finished = true; 

      OPEN alternative_search_cur; 

      alternative_search_loop : loop 

        FETCH alternative_search_cur INTO  p_alternative_str; 

        IF alternative_search_loop_finished then 
            set alternative_search_loop_finished = false;
            close alternative_search_cur;
            leave alternative_search_loop; 
        END IF; 

        -- select search_b from Product_Search_Alternatives where search_a = p_alternative_str;
        select p_item,p_searchtext; 
        /*
        update productsearch
        set searchbox = Concat(searchbox,' ',v_alt_txt)
        where item = v_item;        
        */
        -- select v_alt_txt;

        END loop alternative_search_loop;

    end begin_block2;

END loop srchbox_loop;
END

虽然您的程序在查找备用匹配字符串时在第二个块中有一些禁用的内容,但我不确定您要获取什么,所以我将该块的大部分内容都注释掉了。

还有你这个东西其实没有任何用处,所以我把它去掉了。如果您需要它,我会重新添加变量游标和提取,但还需要添加列以插入 SPLIT_VALS table.

我的方法是使用 INSTR() 函数来确定给定字符串或字符的第一个位置...在这种情况下,您正在寻找 PIPE 字符。一旦确定,我就继续从字符串中删除刚刚处理的字符串的任何部分,从而不断缩小 p_searchtext 字符串,直到什么都不剩下。我认为您检查每个字符的逻辑一直在失败,或者没有将此类项目视为双 space 从而创建双“||”循环中描述和涵盖的字符。

除了 INSTR() 之外,您还可以使用 SUBSTRING_INDEX(str, delim, count) 进行类似操作以获取空字符串或找到的位置...希望这对您有所帮助。 ..

CREATE DEFINER=`root`@`localhost` 
PROCEDURE `sp_update_productsearch_datasync`()
BEGIN
   -- regardless of any possible results,
   -- prepare temp table to store string split into word parts
   drop TABLE IF EXISTS split_vals;      
   create temporary TABLE split_vals(vals varchar(1000));  

   DECLARE p_searchtext longtext default ''; 
   DECLARE search_loop_finished boolean default false; 

   DECLARE srchbox_cur CURSOR FOR 
      SELECT DISTINCT searchbox 
         FROM  productsearch 
         where searchbox is not null 
         limit 10; 

   DECLARE continue HANDLER for NOT found 
      SET search_loop_finished = true; 

   open srchbox_cur;   
   srchbox_loop : loop   
      FETCH srchbox_cur INTO  p_searchtext; 
      -- exit immediately if no result
      IF search_loop_finished then 
         leave srchbox_loop; 
      END IF; 

      -- preset any SPACES into a common PIPE character
      set p_searchtext = rtrim(replace(p_searchtext,' ','|')); 

      declare str       varchar(500); 
      declare pipePos   int default 0;

      split_val_loop : loop 

         -- if no text string left to work with, exit loop
         if length(p_searchtext) = 0 THEN 
            leave split_val_loop; 
         end if; 


         -- does the p_searchtext have any more pipe characters left in it?
         set pipePos = INSTR('|', p_searchtext);

         -- in case there is a double space could create "test||strings|||more"
         -- you would never want to insert a "|" string value
         if pipepos = 1
            set p_searchtext = substr(p_searchtext, 2);
            iterate split_val_loop;
         end if;

         -- if not, do the insert for whatever is remaining and clear flag
         -- for the split_val_loop
         if pipePos = 0 then
            set str = p_searchtext;
            -- clear text since this was the end
            set p_searchtext = '';
         else
            -- there IS a pipe.  get portion UP TO, but not including the pipe
            -- do not include the pipe character in string returned
            set str = left( p_searchtext, pipePos -1);
            -- remove the entire length of the found string including the pipe
            set p_searchtext = SUBSTR( p_searchtext, pipePos +1)
         end if

         -- there HAD to be something since search text was > 0
         insert INTO split_vals VALUES (str); 
      end loop split_val_loop;

   -- I would continue ALL fetched search records and split them all first
   -- so you don't keep requerying the list as it grows for each 10 records
   end loop srchbox_loop;

   -- close cursor once out of the loop
   close srchbox_cur;

   -- uncomment below to pre-check results of split values
   -- select * from split_vals;

   -- now the next set of processing
   DECLARE alternative_search_loop_finished boolean default false; 
   DECLARE p_alternative_str VARCHAR(1000) default ''; 

   DECLARE alternative_search_cur CURSOR FOR 
      SELECT DISTINCT vals FROM  split_vals; 

   DECLARE continue HANDLER for NOT found 
      SET alternative_search_loop_finished = true; 

   OPEN alternative_search_cur; 

   alternative_search_loop : loop 
      FETCH alternative_search_cur INTO p_alternative_str; 

      IF alternative_search_loop_finished then 
         leave alternative_search_loop; 
      END IF; 

      -- select search_b 
      --    from Product_Search_Alternatives 
      --    where search_a = p_alternative_str;

      -- select p_item, p_searchtext; 

      /*
      update productsearch
      set searchbox = Concat(searchbox,' ',v_alt_txt)
      where item = v_item;        
      */
      -- select v_alt_txt;
   end loop alternative_search_loop;

   -- close cursor OUT of the loop
   close alternative_search_cur; 

-- end of procedure
end