oracle转postgreSQL修改点

从2019年开始,就有一个很火热的话题:“去O化”。O就是oracle,也就是将oracle替换成别的数据库。为什么要去O?大致有以下原因:

  • oracle是收费的,为了进一步降低成本;
  • 以美国为首的西方国家对华科技种种遏制行为,最近越闹越厉害,最近docker的付费服务就禁止中国企业使用;
  • 甲骨文公司中国区大幅度裁员,或将放弃中国市场也说不定;
  • 2020年12月31起,甲骨文公司将不再对oracle11.2版本提供技术支持,即出现bug也不会维护了。

鉴于以上种种原因,很多企业都在更换数据库,但是如果新的数据库语法和oracle差别很大,那工作量会特别大,权衡之下,postgreSQL是个不错的选择。

本人前两周就在做这个“去O化”,将遇到的改造点记录下来,供大家参考。

1、jar包/maven依赖的更换:

驱动包要换成postgresql-xxx.jrex.jarx表示版本。如果是maven项目,则添加如下依赖:

<dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <version>版本</version>
</dependency>

欢迎大家关注我的公众号 javawebkf,目前正在慢慢地将简书文章搬到公众号,以后简书和公众号文章将同步更新,且简书上的付费文章在公众号上将免费。


2、driverClassName等信息的更换:

datasource.driverClassName=org.postgresql.Driver
hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect

3、字段类型问题:

  • 主外键字段类型问题:A表的主键在B表做外键时,这个字段在两张表的类型一定要一致,否则连接查询会报错。
  • 实体类与数据表字段类型问题:实体类字段类型一定要与数据表字段类型对应,否则映射的时候就报错了。
  • 查询条件的字段类型问题:假如数据表中id字段类型是int4,查询条件传String类型的1,是会报错的,要用Integer类型,而oracle不会报错,会自动进行类型转换。

4、postgre与java字段类型对照表:

以下是常用字段类型对照:

postgre java
varchar String
char String
text String
int2/int4 Integer
int8 Long
float4 Float
float8/money Double
numeric Bigdecimal
bool Boolean
bytea byte[]

5、序列问题:

  • oracle获取序列:my_sequece.nextval
  • postgre获取序列:nextval('my_sequece')

6、sysdate替换方案:

oracle postgre
当前日期 时间 sysdate now()
当前日期 trunc(sysdate) now() :: date
?分钟前 sysdate - ?/24/60 now() - (? || 'min')::interval
?天前 sysdate - ? now() - (? || 'day')::interval

7、NVL函数替换方案:

oracle中的NVL(arg1, arg2)用来设置默认值,arg1为空就设置为arg2。postgre中可以用coalesce(arg1, arg2)实现相同效果。

8、分页问题:

比如要查询user表第一页,每页显示10条数据:

  • oracle中用rownum进行分页:
select * from (select aa.*, rownum rn from (select * from user) aa where rownum <= 11 ) where rn > 1;
  • postgre中用limit进行分页:
select * from user limit 10 offset 1

查询user表5条数据:

  • oracle写法:
select * from user where rownum <= 5
  • postgre写法:
select * from user limit 5

9、不等于的问题:

postgre中column !=-?会报错,负号和数字应用括号括起来,或者!=统一改成<>

10、数字类型字段模糊查询问题:

非String类型的字段要进行模糊查询,需要先将数据库字段类型转成varchar,如下:

and cast(user_phone as varchar) LIKE ?

11、update语句相关问题:

postgre中,update语句不能设置表别名,否则会报错。

12、count和order by的问题:

select count(*)的语句不能加order by,否则会报错。

13、order by的问题:

group by的字段一定要在select中查出来,并且如果group by的字段有使用函数,select的时候也要使用相同的函数,例如:

select upper(user_id) from user order by upper(user_id)

14、blob类型的问题:

oracle中用blob类型可以存储文件,在java中也用blob类型对应。postgre与之对应的是bytea,在java中用byte[]数组对应就可以了。

15、clob类型的问题:

oracle中用clob存储大文本,在java中也用clob类型对应。postgre与之对应的是text,在java中直接用String对应就可以了。

16、decode函数问题:

oracle中的decode(arg1, arg2, arg3, arg4)函数,表示:当 arg1 等于 arg2 时,取 arg3 ,否则取 arg4。postgre中没有类似的函数,可以用如下方式实现:

case when arg1 = arg2 then arg3 else arg4 end

17、to_date函数的问题:

特别注意,postgre中to_date函数转出来的是不带时分秒的时间,如果想要带时分秒的,需要用to_timestamp

18、substr函数的问题:

substr(arg, begin, num)函数,表示对arg进行截取,从第begin位开始,截取num个。oracle中,arg可以是字符串也可以数字类型,但是postgre中只支持对字符串的截取,如果要对数字进行截取,得写成:SUBSTR(1.23 :: TEXT,1,3)。还有一点,oracle中substr(1.23, -2)表示截取最后两位,结果就是23,postgre中不支持这种用法,要实现相同功能,可以用right函数:right(1.23::text, 2)

19、 listagg(column1, ',') within group(column2)函数的问题:

这个函数的意思是将column2相同的多行记录的column1的值合并成一行,例如:

SELECT tr.tr_gw_no,
        listagg(tr.tr_status, ',') WITHIN GROUP(ORDER BY tr.tr_status) status
FROM trade tr
where tr_gw_no = 12198006
     or tr_gw_no = 12167001
GROUP BY tr.tr_gw_no;

查询结果就是:


查询结果

postgre中可以用string_agg函数实现相同的功能,具体用法如下:

SELECT
    tr_gw_no,
    string_agg ( tr_status :: TEXT, ',' ) status
FROM
    trade 
WHERE
    tr_gw_no = 12198006 
    OR tr_gw_no = 12167001 
GROUP BY
    tr_gw_no;

20、start with connect by函数的问题:

oracle的这个函数是用来查树形结构的,即同一张的表的记录有父子级关系的那种。oracle中用法如下:

select module_id
    from sys_modules
start with module_id = ?
connect by prior module_id = module_fid;

这就表示查询module_id?的所有子module,即父模块idmodule_fid?的所有的记录。postgre可以用WITH RECURSIVE实现相同的效果,如下:

WITH RECURSIVE subtabela AS (
    SELECT
        module_id 
    FROM
        sys_modules 
    WHERE
        module_id = ? UNION ALL
    SELECT
        tt.module_id 
    FROM
        sys_modules tt
        INNER JOIN subtabela st ON tt.module_fid = st.module_id 
    ) SELECT
    * 
FROM
    subtabela;

21、存储过程调用的问题:

postgre11开始,支持存储过程procedure,之前的版本只支持function。通过代码去调用存储过程时,要注意以下三点:

  • 调用存储过程的sql语句不需要加大括号,加了大括号的调用的是function而不是procedure;
  • 如果存储过程中用了事务,那个在代码中调用时就不要使用spring的事务了,否则会冲突;
  • 如果存储过程有inout参数,表示这个即是输入又是输出参数,都要进行设置,oracle可以只当作输入或者输出来用。

比如现在有一个名为test_procedure(IN "id" int4, INOUT "result" int4)的存储过程,java中调用方式如下:

Session session = sessionFactory.getCurrentSession();
Connection conn = session.connection();
CallableStatement cs = null;
Integer returnInfo = -1;
cs = conn.prepareCall("call p_paynum_processing_create(?,?)");
// oracle中调用要加大括号
// cs = conn.prepareCall("{call p_paynum_processing_create(?,?)}");
// 输入的参数
cs.setInt(1, id.intValue());
// 输出的参数
cs.setInt(2, -1); // oracle中这一行可以不用
cs.registerOutParameter(2, Types.INTEGER);
// 执行存储过程
cs.execute();
// 获取返回值,-1为操作异常
returnInfo = cs.getInt(2);

22、连接查询的问题:

oracle中外连接可以这样写:

select * from tableA a, tableB b  where a.id = b.id(+);

(+)的一方是副表,另一方是主表,即上面那种写法表示左外连接。postgre不支持这种写法,可以用left join代替。

23、instr函数的问题:

instr函数表示包含,postgre中可以用strpos函数替代。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343