mysql6支持connect by,非专业处置:Oracle->MySQL的Connect by迁移

非专业处理:Oracle->mysql的Connect by迁移

这两天在弄一个系统迁移,以适应小平台的要求。数据库要从Oracle移植到Mysql。

比较了种种,包括数据类型、主键自增/序列、字符串函数之后,就剩下一个“层次递推查询”最难办。

具体是这样的:

Oracle的connect by语句能够很好的支持:

1、只根据id和parentId两个字段,便可以查找一个结点的所有子孙结点

2、只根据Id和parentId连个字段,便可以查找一个结点的根(表是一个森林,非树)

MYSQL对等的语句处理这样的功能。

示例的表结构(MySQL):

CREATE TABLE `node` ( `id` bigint(20) NOT NULL auto_increment, `parentId` varchar(20) default NULL, `name` varchar(20) default NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB

欢迎大家阅读《非专业处置:Oracle->MySQL的Connect by迁移》,跪求各位点评,by 搞代码

第2个问题比较好解决,在此不是主要的讨论点。关键是第1个。

比如有如下数据:

mysql> select * from node; +----+----------+-------+ | id | parentId | name | +----+----------+-------+ | 1 | NULL | root | | 2 | 1 | two | | 3 | 1 | three | | 4 | 2 | four | | 5 | 2 | five | | 6 | 3 | six | | 7 | 3 | seven | | 8 | 4 | eight | +----+----------+-------+ 8 rows in set (0.02 sec)

那么id=2的所有子孙,将是id为:4,5,8的纪录。

本人不是数据库专家,所以确实很郁闷。不过还好对MYSQL还算有所了解,做了一下一个存储过程来应付:

(该存储过程,不具有通用性,针对的是特定的表名以及id,parentId字段名称,不同的表,需要不同的存储过程,采用selectXxxxxPosterity的命名方式;而且要求子孙的id必须大于父亲的id。)

CREATE PROCEDURE `selectNodePosterity`(IN startId BIGINT) NOT DETERMINISTIC SQL SECURITY DEFINER COMMENT '' BEGIN DECLARE _id bigint DEFAULT 0; DECLARE _path VARCHAR(255); DECLARE _last bigint DEFAULT 0; CREATE TEMPORARY TABLE IF NOT EXISTS `temp_table` ( `id` bigint(20) NOT NULL auto_increment, `path` varchar(20) default NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB TYPE = HEAP; delete from temp_table; insert into temp_table(id, path) select src.id, src.id from node src where id=startId; set _id = startId; set _path = startId; WHILE _id <> 0 DO insert into temp_table(id, path) select src.id, concat(concat(_path, '/'), src.id) from node src where src.parentId=_id; set _last = _id; set _id = 0; select id, path into _id, _path from temp_table where id>_last limit 1; END WHILE; select src.*, temp_table.path from temp_table, node src where temp_table.id= src.id order by temp_table.path; END;

运行效果:

mysql> call selectNodePosterity(2); +----+----------+-------+-------+ | id | parentId | name | path | +----+----------+-------+-------+ | 2 | 1 | two | 2 | | 4 | 2 | four | 2/4 | | 8 | 4 | eight | 2/4/8 | | 5 | 2 | five | 2/5 | +----+----------+-------+-------+ 4 rows in set (0.00 sec) Query OK, 0 rows affected, 2 warnings (0.02 sec)

e7ce419cf2d6ad34d01da2ceb8829eed.png

微信 赏一包辣条吧~

023a57327877fb4402bcc76911ec18ea.png

支付宝 赏一听可乐吧~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MySQL 使用的是标准SQL语言,而Oracle在自己的SQL语法中添加了CONNECT BY PRIOR关键字来实现递归查询。 在MySQL中,我们可以通过使用递归查询来实现类似的功能。具体步骤如下: 1. 创建一个临时表,用于存储递归查询的结果。这个表可以包含与要查询的原表相同的字段。 2. 插入初始的根节点数据到临时表中。 3. 使用循环语句来进行递归查询,直到找到所有的子节点。 4. 在每次循环中,根据已查询到的节点,通过查询原表将相应的子节点插入临时表中。 5. 直到没有新的子节点为止,即可得到所有满足条件的节点数据。 可以使用MySQL的存储过程来实现上述逻辑,具体代码如下所示: DELIMITER // CREATE PROCEDURE mysql_connect_by_prior() BEGIN -- 创建临时表 CREATE TEMPORARY TABLE IF NOT EXISTS temp_table ( id INT PRIMARY KEY, parent_id INT, name VARCHAR(255) ); -- 插入根节点到临时表 INSERT INTO temp_table (id, parent_id, name) SELECT id, parent_id, name FROM your_table WHERE parent_id IS NULL; -- 循环查询插入子节点到临时表 REPEAT INSERT INTO temp_table (id, parent_id, name) SELECT t.id, t.parent_id, t.name FROM your_table t JOIN temp_table tt ON t.parent_id = tt.id WHERE t.id NOT IN (SELECT id FROM temp_table); UNTIL ROW_COUNT() = 0 END REPEAT; -- 查询最终结果 SELECT * FROM temp_table; -- 删除临时表 DROP TEMPORARY TABLE temp_table; END // DELIMITER ; 调用存储过程: CALL mysql_connect_by_prior(); 这样就可以在MySQL中实现类似Oracle中的CONNECT BY PRIOR递归查询的功能了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值