查询 运行 无穷无尽(嵌套 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
我已经写了这个查询,但可能存在一些我找不到的逻辑错误。游标或游标内的循环永远是 运行,一段时间后我得到最大结果数达到错误。
提前致谢。
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