Mysql实现Oracle中的Start with...Connect by方式

 更新时间:2024年12月23日 08:59:01   作者:HNT_Wings  
文章总结:作者在迁移数据库时,使用了Oracle的startwith进行树的递归查询,但遇到了一些问题,通过搜索和修改,作者成功地使用存储过程和预处理语句来实现动态查询,并解决了变量声明和预处理语句的问题

Mysql Oracle中的Start with...Connect by

工作需要,迁移数据库时发现使用了Oracle中的start with来进行树的递归查询,所以自己动手丰衣足食。

通过一番搜索后发现

大家的实现基本都是这样的:

CREATE FUNCTION queryChildrenAreaInfo(areaId INT)
RETURNS VARCHAR(4000)
BEGIN
DECLARE sTemp VARCHAR(4000);
DECLARE sTempChd VARCHAR(4000);

SET sTemp='$';
SET sTempChd = CAST(areaId AS CHAR);

WHILE sTempChd IS NOT NULL DO
SET sTemp= CONCAT(sTemp,',',sTempChd);
SELECT GROUP_CONCAT(id) INTO sTempChd FROM t_areainfo WHERE FIND_IN_SET(parentId,sTempChd)>0;
END WHILE;
RETURN sTemp;

但是这样的代码没法复用(而且我的navicat居然建立函数失败,或者各种错误,所以我使用了存储过程,效果一样),所以我们使用set和execute来进行语句的拼接和执行,

修改后

如下:

CREATE PROCEDURE getChildList
IN rootId DECIMAL(65),
IN tablesname VARCHAR(6000),
OUT sTemp VARCHAR(6000)
BEGIN
DECLARE sTempChd VARCHAR(4000);

SET sTemp='$';
SET sTempChd = CAST(rootId AS CHAR);

WHILE sTempChd IS NOT NULL DO
SET sTemp= CONCAT(sTemp,',',sTempChd);
set @sqlexe = concat("SELECT GROUP_CONCAT(id) INTO sTempChd FROM " , tablesname , " WHERE FIND_IN_SET(parentId,sTempChd)>0;")
prepare sqlexe from @sqlexe;
execute sqlexe;
END WHILE;
END;

这样一来我们就可以将表名作为参数传入,但是一番执行后,你会发现,哦豁,它居然报了这样一个错:

1327 - Undeclared variable: sTempChd;

这个低级错误困扰了我半天,我不是声明了sTempChd为declare吗?

答案很简单

预处理语句(也就是我们的prepare)中,只接受@声明的参数。因为在存储过程中,使用动态语句,预处理时,动态内容必须赋给一个会话变量,也就是@形式声明的变量,而declare声明的是存储过程变量,具体的内容涉及到更深的知识,我暂时无法找到原因。

前文是自上而下的查询,自下而上的查询其实很简单,只要替换一下参数和语句内容就可以了,

具体如下:

CREATE PROCEDURE `getParentList`( 
	IN rootId DECIMAL(65,0), 
	IN tablesname VARCHAR ( 500 ),
	OUT sTemp VARCHAR ( 6000 ) )
BEGIN
	DECLARE
		PARENTID DECIMAL(65);
	SET sTemp = '$';
	SET @sTempChd = cast(rootId as char);
	WHILE @sTempChd <> 0 DO
		SET sTemp = concat( sTemp, ',', @sTempChd );
		SET @sqlcmd = CONCAT("SELECT PARENTID into @sTempChd FROM " , tablesname , " WHERE CATEID = " , @sTempChd , ";");
		PREPARE stmt FROM @sqlcmd;
		EXECUTE stmt;
	END WHILE;
	DEALLOCATE PREPARE stmt;
END

别忘了,最后要执行一下deallocate语句,释放预处理sql,免得session的预处理语句过多,达到max_prepared_stmt_count的上限值。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • RR与RC隔离级别下索引和锁的测试脚本示例代码

    RR与RC隔离级别下索引和锁的测试脚本示例代码

    这篇文章主要给大家介绍了关于RR与RC隔离级别下索引和锁的测试脚本的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-12-12
  • mysql中GROUP_CONCAT函数使用技巧及问题详解

    mysql中GROUP_CONCAT函数使用技巧及问题详解

    这篇文章主要给大家介绍了关于mysql中GROUP_CONCAT函数使用技巧及问题的相关资料,GROUP_CONCAT是MySQL中的一个聚合函数,它用于将多行数据按照指定的顺序连接成一个字符串并返回结果,需要的朋友可以参考下
    2023-11-11
  • 将图片储存在MySQL数据库中的几种方法

    将图片储存在MySQL数据库中的几种方法

    今天小编就为大家分享一篇关于将图片储存在MySQL数据库中的几种方法,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-03-03
  • Explain命令在优化查询中的实际应用

    Explain命令在优化查询中的实际应用

    在MySQL中,EXPLAIN命令是一种非常重要的查询优化工具,它可以帮助我们分析SQL查询语句的执行计划,以及如何优化它们。本文介绍了Explain命令在优化查询中的实际应用,感兴趣的小伙伴可以参考阅读
    2023-04-04
  • Mysql利用group by分组排序

    Mysql利用group by分组排序

    这篇文章主要为大家详细介绍了Mysql利用group by分组排序,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-12-12
  • MySQL 客户端不输入用户名和密码直接连接数据库的2个方法

    MySQL 客户端不输入用户名和密码直接连接数据库的2个方法

    MySQL 客户端不输入用户名和密码直接连接数据库的2个方法,大家可以测试下。
    2009-07-07
  • MySQL Group by的优化详解

    MySQL Group by的优化详解

    这篇文章主要介绍了MySQL Group by 优化的相关资料,帮助大家更好的理解和学习使用MySQL,感兴趣的朋友可以了解下
    2021-03-03
  • Mysql update多表联合更新的方法小结

    Mysql update多表联合更新的方法小结

    这篇文章主要介绍了Mysql update多表联合更新的方法小结,通过实例代码给大家介绍了mysql多表关联update的语句,感兴趣的朋友跟随小编一起看看吧
    2020-02-02
  • 虚拟机linux端mysql数据库无法远程访问的解决办法

    虚拟机linux端mysql数据库无法远程访问的解决办法

    最近在项目搭建过程中遇到一问题,有关虚拟机linux端mysql数据库无法远程访问,通过查阅相关数据库资料问题解决,下面把具体的解决办法分享给大家,有需要的朋友可以参考下
    2015-08-08
  • centos7安装mysql5.7的踩坑记录

    centos7安装mysql5.7的踩坑记录

    最近在做项目中发现CentOS 7下升级MySQL5.7的一个坑,所以下面这篇文章主要给大家介绍了关于centos7安装mysql5.7的踩坑记录,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2022-05-05

最新评论