去IOE(IBM服务器,Oracle,EMC存储),Oracle迁移
postgreSQL部。。。
Oracle迁移postgreSQL部分问题解决⽅案
“去IOE化"理念最早是由阿⾥巴巴提出。具体就是要把公司⾥IBM服务器、Oracle数据库、EMC存储都替换掉,
更换为开源或国产化的选项,postgreSQL 对Oracle兼容性⽐较好。
1.当前时间 oracle的sysdate
处理⽅法:未开启事务时⽤now()替换,⼀般项⽬也是没有事务的。在事务中⽤到sysdate时,建议⽤clock_timestamp()替换。
例⼦
select sysdate from dual  等价于  select now()
2.序列 oracle的SEQNAME.NEXTVAL
处理⽅法:pg的NEXTVAL('SEQNAME')等效于SEQNAME.NEXTVAL
pg还提供了其他⼏种处理序列的⽅法
currval('SEQNAME')  输出sequence的当前值
setval('SEQNAME')  设置sequence将要输出的下⼀个值
例⼦
select SEQNAME.NEXTVAL from dual 等价于 NEXTVAL('SEQNAME')
3.虚表 oracle的from dual
处理⽅法:直接去掉
4.空值处理函数 Oracle的nvl
处理⽅法: NVL可以⽤COALESCE函数替换
例⼦
select nvl(null,0) from dual 等价于 select COALESCE(null,0)
5.空值处理函数 Oracle的nvl2
处理⽅法:select nvl2(列名,1,0) from dual 等价于 select case when 列名 is null then 0 else 1
------⽤case when 解决
例⼦
select nvl2(null,1,0) from dual 等价于 select case when null is null then 0 else 1 end
6.⾃动类型转换
pg不⽀持强⾃动类型转换解决⽅法使⽤
⽅法1:cast(列名 as 类型)或者
⽅法2:列名::类型来转换
类型问题多集中在字符和数字之间
pg⽀持弱⾃动转换⽐如  numeric和integer,smallint,bigint之间是可以⾃动转换的。
text和character之间的转换
例⼦ 字符和数字之间的转换解决⽅案
select * from  tb_hello where '1'=1
等价于
select * from  tb_hello where cast('1' as integer)=1
select * from  tb_hello where '1' :: integer=1
7.INSTR函数 字符查函数
Oracle的instr()有两种表达格式
格式⼀:instr( string1, string2 )    // instr(源字符串, ⽬标字符串)
格式⼆:instr( string1, string2 [, start_position [, nth_appearance ] ] )  // instr(源字符串, ⽬标字符串, 起始位置, 匹配序号)
对于格式1
处理⽅法直接⽤strpos替换
对于格式2
处理⽅法重写⼀个函数instr来处理(百度搜⼀下)
例⼦
select instr('hello','l') from dual 等价于
select strpos('hello','l')
8.substr() 截取字符函数
oracle的substr()有两种格式
格式1: substr(string string, int a, int b);
##从字符串的第a位开始截取b个字符形成新字符串
格式2:substr(string string, int a) ;
对于格式1:
如果a>0 那么可以直接替换为substring()
如果a=0 那么替换为1
如果⼩于0  处理就⽐较⿇烦下⾯会给出具体处理办法。
对于格式2:
直接替换为substring()
例⼦
格式1(a>0)和a=0的情况  --格式2情况就不讲解了
select substr('hello',0,2) from dual  ##截取字符第⼀位开始2位返回截取的字符
select substr('hello',1,2) from dual  ##截取字符第⼀位开始2位返回截取的字符两者结果⼀致
等价于
select substring('hello',1,2)
select substr('hello',1,2)
对于a<0的情况
select substr('hello',-a,2) from dual ##oracle从字符串倒数定位字符,所以意思就是从str倒数第⼀位开始截取2位组成字符串解决⽅法:
select substring('hello',CHAR_LENGTH('hello')-a+2,2) ##具体意思⾃⼰理解
9.连接
oracle的连接可以简写为(+)
解决办法:替换为join  ⼝诀:那个表的字段后(+)那么就left join 那个表。例⼦
select a.id,b.name
from tb_hello a,tb_hi b
where a.id=b.id(+)
等价于
select a.id,b.name
from tb_hello a
left join tb_hi b on a.id=b.id
10,层次查询(递归)
oracle的start with connect by 函数实现层次查询
oracle 时间转换对于下表sr_menu给出递归查询在oracle和pg的实现
id | parent |  title  | recursion_level
----+--------+---------+-----------------
1 |        | level 0 |              1
2 |      1 | level 1 |              2
3 |      1 | level 1 |              2
4 |      1 | level 1 |              2
5 |      3 | level 2 |              3
解决:pg中使⽤WITH RECURSIVE语句实现递归
例⼦(对于上⾯的sr_menu表给的例⼦)
oracle 写法:
select * from sr_menu          ##需要查询的列。
start with id = 1    ##查询初始条件
connect by prior id = parent;  ##递归条件
pgsql 写法:
WITH RECURSIVE a AS (
SELECT id, parent, title
FROM sr_menu
WHERE id = 1              ##查询初始条件
UNION ALL
SELECT d.id, d.parent, d.title
FROM sr_menu d
JOIN a ON a.id = d.parent )  ##递归条件
SELECT * FROM a;      ##需要查询的列。
11.数据库对象⼤⼩写
oracel  不区分⼤⼩写
pgsql  ⼤⼩写区分创建数据库对象时要⼩写,这样才不区分SQL的⼤⼩写12.ROWNUM虚列
oracle会为每个表默认⽣成⼀个虚列ROWNUM,pg不会。
在我们使⽤ROWNUM⼀般分2种情况
1.限制结果集数量,⽤于翻页等处理⽅法为 limit关键字
2.⽣成⾏号处理⽅法为⽤ROW_NUMBER() OVER()来⽣成⾏号例⼦
对于第⼀种情况
select *  from  tb_hello  where rownum <=10
替换为
select *  from  tb_hello  where 1=1 limit 10    ##注意limit只能⽤在where条件结束之后
第⼆种情况
select *,rownum from tb_hello
替换为
select *,ROW_NUMBER() OVER() as rownum from tb_hello
13.DECODE等判断函数
语法:decode(条件,值1,返回值1,值2,返回值2,...值n,返回值n,缺省值) ##当条件的值为值1时,返回返回值1,为值2时返回返回值2......
oracle的decode类似java的case语句
所以在pg中也是⽤case when语句来实现替换
例⼦
select decode(X,A,B,C,D,E)from dual
等价于
select case X when A then B when C then D else E end
<_char()
to_char()在oracle中⼏乎可以满⾜任何⼊参转换
在pg中却不同,举例说明
例⼦
select to_char('hello') oracle可⾏,pg报错  ##pg不能转换字符类型
解决: 1,重写to_char()函数⽀持⼊参为字符串  2.使⽤cast()替换to_char()
select to_char(1111)  oracle可⾏,pg报错  ##pg转换数值型时必须接上精度
解决
select to_char(1111,'fm99999')
<_date()
to_date()函数
oracle:
to_date('','YYYYMMDD')只能匹配'20200102'
'yyyy/MM/dd'和'yyyy-MM-dd'匹配所有三种时间格式字符串('20200304','2020-03-04',2020/03/04')
pg:
pgsql的to_date()函数格式要求严格⼀些,‘yyyyMMdd’匹配‘2020-01-03’和‘20200103’ 。 ‘yyyy/MM/dd’匹配‘2020-01-03’和 ‘2020/01/03’  。 ‘yyyy-MM-dd' 匹配  ‘2020-01-03’和 ‘2020/01/03’  。
16.NULL和''
ORACLE认为''等同于NULL
pg认为NULL和''不同
关于null和''解决可以⽤case when或者COALESCE来处理
oracle的 LENGTH('')为NULL
pg的LENGTH('')为0
oracle的TO_DATE('','YYYYMMDD')为空
pg的TO_DATE('','YYYYMMDD')为0001-01-01 BC
oracle的TO_NUMBER('',1)为NULL
pg的TO_NUMBER('',1),报错
18.ADD_MONTHS(DATE,INT)
oracle的ADD_MONTHS(DATE,INT) 指在给定的时间戳上增加或减少固定个⽉份
解决⽅法 1.创建add_month(date,int)函数  2.⽤- interval关键字解决
例⼦
select add_months(sysdate,1) from dual
等价于
select now() -interval '1 month'
19.⼦查询别名
oracle ⼦查询可以没有别名
select * from (
select * from tb_b_dim_latn_all);
或者
select * from (
select * from tb_b_dim_latn_all);
pg 必须写别名
select * from (
select * from tb_b_dim_latn_all) t;
20.查询当前登陆⽤户
SELECT USER FROM DUAL  ##oracle
select current_user    ##pg
21.MINUS 取差集
##orace
MINUS语句:返回两个结果集的差(即从左查询中返回右查询没有到的所有⾮重复值)。
##pg
EXCEPT 返回两个结果集的差(即从左查询中返回右查询没有到的所有⾮重复值)
例⼦
select 1,2,3 from dual
MINUS
select 1,2,3 from dual
等价于
select 1,2,3
EXCEPT
select 1,2,3

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。