oracle 迁移至 mysql 部分语句的转换

时间:2021-07-01 14:55:28

前几天吧系统从oracle往mysql上迁移,很多的语句是比较简单的,就是一些函数的修改如to-date等

但是也有几个比较棘手的,这里记录下


第一、row_number() over(partition by   

首先要了解下oracle中这个函数的用法,看个例子

select t.*,row_number() over(partition by t.owner order by y.createDate desc) rn from test t

这个语句的意思就是,把test这个表的数据按照owner 分组并且给每个分组的里面的数据加上一个序列号,数据格式如下


id       name      owner   createDate  rn

1         aa            001                              1

2          bb           001                              2

3          cc            001                             3

4          dd            002                             1

5           ee           002                              2

6            ff            003                               1

数据搞得不太正规,但是应该能够看懂它的意思吧,


但是在mysql中是没有这个函数的于是乎,找啊找,总算找了个解决方法,如下

SELECT
    heyf_tmp.*,
    IF(@pdept=heyf_tmp.owner ,@rn:=@rn+1,@rn:=1) AS rn,
    @pdept:=heyf_tmp.owner 
FROM
    (
        SELECT
            yv.*
        FROM
            test yv
        ORDER BY
            yv.owner  ,
            yv.createDate  DESC
    )
    heyf_tmp ,
    (
        SELECT
            @rn :=0 ,
            @pdept := NULL ,
            @rn:=0
    )
    aa

具体是什么意思,不是很清楚,不过先解决问题再说


第二、oracle树形查询


oracle树形查询现成的方法

select distinct t.id as id, t.name 

from test t
                start with id=‘’
               connect by prior id = parentid

但是mysql中是没有这个方法的,于是只能自己定义函数或者过程,我这里用的是过程

如下

CREATE PROCEDURE Pro_GetTreeList`(in pid varchar(36))
begin 
   declare lev int;
   set lev=1;
   drop table if exists tmp1;    
   CREATE TABLE tmp1(id VARCHAR(40),name varchar(50),parentid varchar(40) ,levv INT);    
   INSERT tmp1 SELECT id,name,parent_id,1 FROM `test` WHERE parent_id=pid;    
  while  row_count()>0 
    do     set lev=lev+1;     
     INSERT tmp1 SELECT t.id,t.name,t.parent_id,lev from testt join tmp1 a on t.parent_id=a.id AND levv=lev-1;--查出子节点
  end while ;    
  INSERT tmp1 SELECT id,name,parent_id,0 FROM test WHERE id=pid;   --查出当前节点
end

这个存储过程应该都能看懂吧,就不做多解释了


第三 、函数中定义类似一维、二维数组,


oracle中可以直接定义的,如

return number  is   newList  :=  NewList((1,2,3),(4,5,6));这样可以直接返回   return newList(1,2)    返回的就是2了,

但是mysql中却不能这样写的,不过也有这样的方法解决:

对于一维的来说,很简单,有函数的elt函数,可以直接return   elt(index,'1','2','3');   如果elt(3,'1','2','3')  这样返回的就是 3了,


不过对于二维的来说好像没有现成的函数用了,我的解决方法是改成个表来做,把数据录入到表中,然后去查表,这丫要给你也是可以实现


第四、 mysql中获取汉字的首个大写字母

mysql中遇到了这样的一个问题,网上找到了方法,转载地址://http://blog.csdn.net/lky5387/article/details/11973721

DROP FUNCTION IF EXISTS `getPY`;
DELIMITER ;;
CREATE DEFINER=`root`@`%` FUNCTION `getPY`(in_string VARCHAR(65534)) RETURNS mediumtext CHARSET utf8
BEGIN
DECLARE tmp_str VARCHAR(65534) charset gbk DEFAULT '' ; #截取字符串,每次做截取后的字符串存放在该变量中,初始为函数参数in_string值
DECLARE tmp_len SMALLINT DEFAULT 0;#tmp_str的长度
DECLARE tmp_char VARCHAR(2) charset gbk DEFAULT '';#截取字符,每次 left(tmp_str,1) 返回值存放在该变量中
DECLARE tmp_rs VARCHAR(65534) charset gbk DEFAULT '';#结果字符串
DECLARE tmp_cc VARCHAR(2) charset gbk DEFAULT '';#拼音字符,存放单个汉字对应的拼音首字符
SET tmp_str = in_string;#初始化,将in_string赋给tmp_str
SET tmp_len = LENGTH(tmp_str);#初始化长度
WHILE tmp_len > 0 DO #如果被计算的tmp_str长度大于0则进入该while
SET tmp_char = LEFT(tmp_str,1);#获取tmp_str最左端的首个字符,注意这里是获取首个字符,该字符可能是汉字,也可能不是。
SET tmp_cc = tmp_char;#左端首个字符赋值给拼音字符
IF LENGTH(tmp_char)>1 THEN#判断左端首个字符是多字节还是单字节字符,要是多字节则认为是汉字且作以下拼音获取,要是单字节则不处理。
SELECT ELT(INTERVAL(CONV(HEX(tmp_char),16,10),0xB0A1,0xB0C5,0xB2C1,0xB4EE,0xB6EA,0xB7A2,0xB8C1,0xB9FE,0xBBF7,0xBFA6,0xC0AC
,0xC2E8,0xC4C3,0xC5B6,0xC5BE,0xC6DA,0xC8BB,0xC8F6,0xCBFA,0xCDDA ,0xCEF4,0xD1B9,0xD4D1),
'A','B','C','D','E','F','G','H','J','K','L','M','N','O','P','Q','R','S','T','W','X','Y','Z') INTO tmp_cc; #获得汉字拼音首字符
END IF;
SET tmp_rs = CONCAT(tmp_rs,tmp_cc);#将当前tmp_str左端首个字符拼音首字符与返回字符串拼接
SET tmp_str = SUBSTRING(tmp_str,2);#将tmp_str左端首字符去除
SET tmp_len = LENGTH(tmp_str);#计算当前字符串长度
END WHILE;
RETURN tmp_rs;#返回结果字符串
END;;
DELIMITER ;

第四、 图片clob的修改

系统中的功能是把图片存在blob字段中的,,原来用的是oracle,java中对应的字段是Object,但是mysql中如果这样做却不能独处图片,原因可能是因为在往Object中写数据时出错了,这个号解决,只要把java中对应字段的类型改成byte[]  就行了



第五、mysql中 group_concat  与 find_in_set  用法

在项目中遇到这样的需求,

表event中如下字段                                           表work中如下字段

         id                 ename                                              id            wname              eventid

      1001       事件1                                   1          工作1         1001

      1002       事件2                                   2          工作2         1001,1002

      1003       事件3                                   3          工作3         1001,1003

       现查询了一张work表数据,需要展示id   name   event名称,只用一个sql展示,

       select wname,  (select group_concat(ename) from event where find_in_set(id,eventid) ) as ename  from  work;

这一个sql就可以搞定,find_in_set  用法以逗号分隔开与id进行匹配,返回多条记录,  group_concat为把展示的多行记录做成一列展示并以逗号拼接