有没有简便方法可将Oracle脚本转换为MySQL 8.0可运行的脚本?
Oracle PL/SQL 转 MySQL 8.0 最简方案
你的原脚本逻辑本质是将查询结果批量插入目标表,在MySQL中完全不需要仿写Oracle的游标循环逻辑,直接使用INSERT ... SELECT语法即可实现等价功能,代码量大幅缩减,执行效率也更高。
1 替换第一个PL/SQL块
原逻辑为按酒店、分类分组统计评分后插入RATINGS表,直接用以下单条SQL替代整个DECLARE块:
INSERT INTO RATINGS (RATING, HOTELID, CATEGORYID) SELECT AVG(RATING1), HOTELID1, CATEGORYID1 FROM RATINGS1 WHERE categoryID1 = 4 GROUP BY HOTELID1, CATEGORYID1;
2 替换第二个PL/SQL块
原逻辑为关联reviews和SeedWords表统计后插入RATINGS1表,注意原查询没有写关联条件是笛卡尔积,转换后保持原有逻辑不变:
INSERT INTO RATINGS1 (HOTELID1, CATEGORYID1, RATING1) SELECT a.idhotel, b.categoryid, AVG(b.polarity) FROM reviews a, SeedWords b GROUP BY a.idhotel, b.categoryID, INSTR(a.review, b.seed_words);
注:原逻辑中INSTR返回的lv_count字段没有被使用,所以转换后的查询可以省略该字段。
3 UPDATE语句直接复用
最后一条UPDATE语句MySQL完全兼容,无需修改直接执行即可:
UPDATE RATINGS SET RATING = ROUND(RATING,1);
可选:对齐原PL/SQL游标结构的写法
如果你一定要保留和原Oracle脚本相似的循环结构,可以参考以下MySQL存储过程写法(不推荐,性能远低于INSERT SELECT):
-- 临时修改分隔符避免和存储过程内的分号冲突 DELIMITER // CREATE PROCEDURE batch_insert_ratings() BEGIN DECLARE v_rate DECIMAL(10,2); DECLARE v_hotel INT; DECLARE v_cat INT; DECLARE v_done TINYINT DEFAULT 0; -- 定义游标 DECLARE cur_ratings CURSOR FOR SELECT HOTELID1, AVG(RATING1), CATEGORYID1 FROM RATINGS1 WHERE categoryID1 = 4 GROUP BY HOTELID1, CATEGORYID1; -- 游标遍历结束标识 DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_done = 1; OPEN cur_ratings; loop_insert: LOOP FETCH cur_ratings INTO v_hotel, v_rate, v_cat; IF v_done = 1 THEN LEAVE loop_insert; END IF; INSERT INTO RATINGS (RATING, HOTELID, CATEGORYID) VALUES (v_rate, v_hotel, v_cat); END LOOP loop_insert; CLOSE cur_ratings; END // DELIMITER ; -- 调用存储过程执行 CALL batch_insert_ratings();
内容的提问来源于stack exchange,提问作者NathanC
相关产品推荐
相关产品推荐

