利用mysql存储过程拆分查询出来的字符串的操作
每条数据字符串的结构是:(天天)[100];(新闻)[90];(关键)[100]…这样的结构
期待输出的样子如下:

关键字

数值

天天

100

新闻

90

关键

100

首先拆分一条数据的字符串
把:(天天)[100];(新闻)[90];(关键)[100]
循环拆分成:(天天)[100],在操作拆分成:天天 100
这里我们用到函数
SUBSTRING_INDEX(需要拆分的字符串,以什么符号分割,第几个符号前的字符);
第三个参数为负数时就是取从分割字符起往右侧的字符截取

先定义存储过程变量
 DECLARE i INT(11);#循环变量
 DECLARE max_size INT(20);#获取有多少分隔符
 DECLARE stt VARCHAR(200);#查询每条数据的值
 DECLARE num VARCHAR(20);#循环截取用
 DECLARE k_var VARCHAR(20);#需要插入的名称
 DECLARE k_int VARCHAR(20);#需要插入的值
set stt = select kv from test;
#创建一个临时表,把数据存入,每次执行删除
DROP TABLE IF EXISTS temp_list;#如果存在就删除
CREATE TEMPORARY TABLE temp_list ( #创建临时表 
kv VARCHAR(200) NOT NULL,
cou INT NOT NULL
TRUNCATE TABLE temp_list;#清空
SET max_size = LENGTH(stt) - LENGTH(REPLACE(stt, ';', '')) + 1;
#这里用字符串长度-去掉分割字符的长度+1 声明循环的次数
SET i = 1;
WHILE i <= max_size DO循环开始
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(stt, ';', i),';',-1) INTO num;
#字符分割得到(天天)[100]
SELECT SUBSTRING_INDEX(REPLACE(num,'(',''),')',1) into k_var;
#字符分割得到天天
SELECT SUBSTRING_INDEX(REPLACE(num,']',''),'[',-1) into k_int;
#字符分割得到100
INSERT into temp_list VALUES(k_var,k_int);
#把得到的
SET i= i+1;
END WHILE;
select * from temp_list;
END

就能得到想要的了;
但是这只能针对查询出来一条数据的操作
查询出来是多条数据如:

kv

(天天)[100];(新闻)[90];(关键)[100]

(天天)[100];(新闻)[90];(关键)[100]

(天天)[100];(新闻)[90];(关键)[100]

这样的数据就需要用到游标,循环输出游标,在执行上边的操作。
游标需要

DECLARE done INT DEFAULT 0; # 自定义控制游标循环变量,默认false
#声明游标
#把查询结果赋值给游标tb
 DECLARE tb CURSOR FOR SELECT kv  FROM test ;
 #绑定控制变量到游标,游标循环结束自动转true 
 DECLARE CONTINUE HANDLER FOR NOT FOUND SET done =1;
  #游标循环
  OPEN tb;
   REPEAT
  	 FETCH tb into stt; #把游标tb的字段赋值给标量stt,多个结果值,需注意顺序
 	  IF NOT DONE THEN
	。。。。。这里执行你想要的操作
	END IF;
   UNTIL done END REPEAT;
  CLOSE tb;#关闭游标

我这里还有一个需求那就是需要查询多个表,表中字段一样。
存储过程传入表名,表名为变量
格式为:
table,table1
这时就需要拼接sql
之后用拼接的sql查询把得到的数据赋给游标
但是游标格式
DECLARE tb CURSOR FOR SELECT
无法执行拼接sql
这时需要用到视图功能
把拼接sql执行并放入到视图中
游标在直接查询视图
全部代码如下:

DROP** PROCEDURE IF EXISTS `delete_matches`;
DELIMITER ;;
CREATE DEFINER=`root`@`%` PROCEDURE `test`(IN `table_type` varchar(32))
BEGIN#创建存储过程 传入的表名table_type 格式table,table1
 DECLARE i INT(11);#循环变量
 DECLARE max_size INT(20);#获取有多少分隔符
 DECLARE stt VARCHAR(200);#查询每条数据的值
 DECLARE num VARCHAR(20);#循环截取用
 DECLARE k_var VARCHAR(20);#需要插入的名称
 DECLARE k_int VARCHAR(20);#需要插入的值
 DECLARE done INT DEFAULT 0; # 自定义控制游标循环变量,默认false
 DECLARE max_size_tab INT;
 DECLARE i_tab INT;
 DECLARE tab_name VARCHAR(20);#表名称
 DECLARE temp_sql VARCHAR(400);#拼接sql
 DECLARE head_sql VARCHAR(400);#拼接sql
 DECLARE un_sql VARCHAR(50);#拼接sql
 DECLARE cr_view VARCHAR(50);#拼接sql
 #声明游标
 DECLARE tb CURSOR FOR SELECT kv  FROM v_view ;
 #绑定控制变量到游标,游标循环结束自动转true 
 DECLARE CONTINUE HANDLER FOR NOT FOUND SET done =1;
 SET temp_sql='';#需拼接的语句
 SET head_sql='SELECT kv  FROM ';#需拼接的语句
 SET un_sql = ' UNION ALL ';#需拼接的语句
 SET cr_view = 'create view v_view as ';#创建视图语句
 #循环输出传入的表名
 SET max_size_tab = LENGTH(table_type) - LENGTH(REPLACE(table_type, ',', '')) + 1;
 IF  max_size_tab>1 THEN
 SET i_tab = 1;
 WHILE i_tab<=max_size_tab DO
  #拆分传入的表名
 SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(table_type, ',', i_tab),',',-1) INTO tab_name;
 IF i_tab=max_size_tab THEN#拼接语句时,最后不需要加union all
 SET temp_sql=CONCAT(temp_sql,head_sql,tab_name);#拼接sql语句
 ELSE#多张表拼接语句
 SET temp_sql=CONCAT(temp_sql,head_sql,tab_name,un_sql);#拼接sql语句
 END IF;
 SET i_tab = i_tab+1;
 END WHILE;
 #当传入的表名为一个时,拼接的语句
 SET temp_sql=CONCAT(head_sql,table_type);
 END IF;
 SET temp_sql =CONCAT(cr_view,temp_sql);#拼接创建视图的语句
 SET @sql =temp_sql;
#执行拼接sql
 PREPARE stmt1 FROM  @sql;
              EXECUTE stmt1 ;
              DEALLOCATE PREPARE stmt1;
 #创建临时表
 DROP TABLE IF EXISTS temp_list;#如果存在就删除
     CREATE TEMPORARY TABLE temp_list ( #创建临时表 
      kv VARCHAR(200) NOT NULL,
   cou INT NOT NULL
      TRUNCATE TABLE temp_list;#清空
      #游标循环
  OPEN tb;
   REPEAT
   FETCH tb into stt;
   IF NOT DONE THEN
#每条数据的操作
   #获取最大的循环次数
   SET max_size = LENGTH(stt) - LENGTH(REPLACE(stt, ';', '')) + 1;
   SET i = 1;
   WHILE i <= max_size DO
   SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(stt, ';', i),';',-1) INTO num;
    SELECT SUBSTRING_INDEX(REPLACE(num,'(',''),')',1) into k_var;
    SELECT SUBSTRING_INDEX(REPLACE(num,']',''),'[',-1) into k_int;
    INSERT into temp_list VALUES(k_var,k_int);
    SET i= i+1;
    END WHILE;
   END IF;
   UNTIL done END REPEAT;
   CLOSE tb;
   SELECT kv,sum(cou)  FROM temp_list GROUP BY kv;#分组求和临时表
   DROP VIEW IF EXISTS v_view;#删除视图
DELIMITER ;

总结一下:

1、这个存储过程用到了游标,视图,创建临时表还有一些函数。
2、声明游标那两句要放在定义变量下边,要不是真报错啊。
3、这个过程执行效率怎么样,具体没有试过,只是参考。
4、最后对临时表的操作,就像正常的表一下,可以排序,去多少条啊。