在树形结构中,常常需要根据某一节点来查询其下所有子节点,网上有好几种解决方式,我采用了函数递归,如下:
CREATE FUNCTION `getChildLst`(rootId INT)
RETURNS varchar(400000)
BEGIN
DECLARE sTemp VARCHAR(400000);
DECLARE sTempChd VARCHAR(400000);
SET sTemp = '$';
SET sTempChd = cast(rootId as char);
WHILE sTempChd is not NULL DO
SET sTemp = concat(sTemp,',',sTempChd);
SELECT group_concat(id) INTO sTempChd FROM t_test where find_in_set(pid,sTempChd)>0 ;
END WHILE;
return sTemp;
END
其中用到了四个mysql函数
1)cast():用来获取一个类型的值,并产生另一个类型的值。但是可转换类型有限。还有一个用来做转换的函数是convert(value, type)
语法:cast
(value
as
type);
2)concat():用于将多个字符串连接成一个字符串,返回结果为连接参数产生的字符串。如有任何一个参数为NULL ,则返回值为 NULL。
语法:concat (str1,str2,…)
3)group_concat():将相同的行组合起来,默认逗号分隔
语法:group_concat([DISTINCT] 要连接的字段 [Order BY ASC/DESC 排序字段] [Separator '分隔符'])
4)find_in_set():查询某个字段的值存在于某一集合中的所有符合条件的结果
语法:find_in_set(str,strLIst)
如果str不在strlist 或strlist 为空字符串,则返回值为 0 。如任意一个参数为null,则返回值为 null。
like是广泛的模糊匹配,字符串中没有分隔符,find_in_set 是精确匹配,字段值以英文”,”分隔,find_in_set查询的结果要小于like查询的结果。
在数据量小的时候没问题,等数据量稍微大一点,长度限制问题就来了。首先遇到的是group_concat() 返回结果的长度问题,它默认为1024,可以使用如下语句来查看
<span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;"> </span>show variables like "group_concat_max_len";
当超过1024个字符长度时,会自动截取前1024个字符省略后边的,并且如果截取得当一般不会报错。所以在使用这个函数之前,就要考虑到它的特性,避免因为数据增长产生问题。
对于group_concat() 长度的调整,可到mysql的配置文件 my.ini 中加上。如果使用的是my-defalut.init ,可复制一份更名为 my.init 再做修改,原配置文件不动。
我设置的102400,这个数值可根据具体需求来定。
总之使用这种查询子节点的方法,存在很多长度的瓶颈,如果树的结构变动不太大,倒是可以采用。
参考:http://www.cnblogs.com/fromchaos/archive/2010/12/15/1907031.html
http://dev.mysql.com/doc/refman/5.7/en/string-functions.html