《卸甲笔记》-PostgreSQL和Oracle的SQL差异分析之五:函数的差异(七)

本文涉及的产品
云原生数据库 PolarDB MySQL 版,通用型 2核8GB 50GB
云原生数据库 PolarDB PostgreSQL 版,标准版 2核4GB 50GB
简介:

PostgreSQL是世界上功能最强大的开源数据库,在国内得到了越来越多机构和开发者的青睐和应用。随着PostgreSQL的应用越来越广泛,Oracle向PostgreSQL数据库的数据迁移需求也越来越多。数据库之间数据迁移的时候,首先是迁移数据,然后就是SQL、存储过程、序列等程序中不同的数据库中数据的使用方式的转换。下面根据自己的理解和测试,写了一些SQL以及数据库对象转换方面的文章,不足之处,尚请多多指教。

1、ADD_MONTHS函数

ADD_MONTHS(date,integer) 是Oracle的一个时间运算函数。返回参数date日期的integer个月后的日期。是Oracle日期运算的一个很基本的函数。
PostgreSQL里面没有这个函数。可以使用Interval数据类型的加减来模拟。返回的是一个timestamp的值。也可以自己创建函数来实现它。

Oracle ADD_MONTHS

SQL> select sysdate  from dual;

SYSDATE
--------------
24-8月 -16

SQL> select add_months(sysdate, 2) from dual;

ADD_MONTHS(SYS
--------------
24-10月-16

SQL> select add_months(sysdate, -2) from dual;

ADD_MONTHS(SYS
--------------
24-6月 -16

SQL> select add_months(to_date('2016/08/01', 'YYYY/MM/DD'), -1) from dual;

ADD_MONTHS(TO_
--------------
01-7月 -16

PostgreSQL ADD_MONTHS

postgres=# select now();
             now
------------------------------
 2016-08-24 09:30:10.87367+08
(1 行记录)

postgres=# select add_months(now(),2);
错误:  函数 add_months(timestamp with time zone, integer) 不存在
第1行select add_months(now(),2);
            ^
提示:  没有匹配指定名称和参数类型的函数. 您也许需要增加明确的类型转换.
postgres=# select now() + '2 month';
           ?column?
-------------------------------
 2016-10-24 09:30:35.284043+08
(1 行记录)

postgres=# select now() + '-2 month';
           ?column?
------------------------------
 2016-06-24 09:30:53.23845+08
(1 行记录)

postgres=# select to_timestamp('2016-08-01','YYYY-MM-DD') + '-1 month';
        ?column?
------------------------
 2016-07-01 00:00:00+08
(1 行记录)

postgres=# CREATE FUNCTION add_months(date, int)
postgres-#  RETURNS date AS
postgres-#  'SELECT ($1 + ( $2::text || ''months'')::interval)::date;'
postgres-#  LANGUAGE 'sql';
CREATE FUNCTION
postgres=# select add_months(current_date, 2);
 add_months
------------
 2016-10-24
(1 行记录)

postgres=# select add_months(current_date, -2);
 add_months
------------
 2016-06-24
(1 行记录)

postgres=# select add_months('2016/08/01', -1);
 add_months
------------
 2016-07-01
(1 行记录)

2、LAST_DAY 函数

LAST_DAY(date)函数是Oracle的一个取日期的月末日的函数。
PostgreSQL中没有对应的日期函数。可以自己使用Interval来实现。也可以自己创建函数来实现。

Oracle LAST_DAY

SQL> select sysdate from dual;

SYSDATE
--------------
24-8月 -16

SQL> select last_day(sysdate) from dual;

LAST_DAY(SYSDA
--------------
31-8月 -16

SQL> select last_day(to_date('2016/09/16', 'YYYY/MM/DD')) from dual;

LAST_DAY(TO_DA
--------------
30-9月 -16

PostgreSQL LAST_DAY

postgres=# CREATE FUNCTION LAST_DAY(DATE)
postgres-#  RETURNS DATE AS
postgres-#          'SELECT date(substr(text($1::timestamp +
postgres'#                  ''1 month''),1,7)||''-01'')-1'
postgres-#          LANGUAGE 'sql';
CREATE FUNCTION
postgres=# select current_date;
    date
------------
 2016-08-24
(1 行记录)

postgres=# select last_day(current_date);
  last_day
------------
 2016-08-31
(1 行记录)

postgres=# select last_day('2016/09/16'::date);
  last_day
------------
 2016-09-30
(1 行记录)

3、MONTHS _BETWEEN函数

MONTHS _BETWEEN函数是Oracle的一个判断两个日期之间有几个月的间隔的函数。
PostgreSQL中也没有对应的函数,只能自己通过函数实现。不过由于对于相差月份的算法不一样,结果可能有些差异。下面给出一个例子。

Oracle MONTHS _BETWEEN

SQL> SELECT MONTHS_BETWEEN(TO_DATE('02-02-1995','MM-DD-YYYY'),
  2   TO_DATE('01-01-1995','MM-DD-YYYY')) MONTHS from dual;

    MONTHS
----------
1.03225806

SQL> SELECT MONTHS_BETWEEN(SYSDATE, TO_DATE('01-01-2014','MM-DD-YYYY')) MONTHS from dual;

    MONTHS
----------
31.7571192

PostgreSQL MONTHS _BETWEEN

postgres=# CREATE FUNCTION MONTHS_BETWEEN(DATE,DATE)
postgres-#  RETURNS NUMERIC AS
postgres-#          'SELECT to_number(text(date($1)-
postgres'#                             date($2)),''999999999'')/31'
postgres-#          LANGUAGE 'sql';
CREATE FUNCTION
postgres=# SELECT MONTHS_BETWEEN('1995-02-02'::date,'1995-01-01'::date);
   months_between
--------------------
 1.0322580645161290
(1 行记录)

postgres=# SELECT MONTHS_BETWEEN(CURRENT_DATE, '2014-01-01'::DATE) MONTHS;
       months
---------------------
 31.1612903225806452
(1 行记录)

4、EXTRACT函数

EXTRACT是Oracle用于从一个date、timestamp或者interval类型中截取到特定的部分所用的函数。Oracle只支持截取年、月、日、时、分、秒,时区时,时区分、时区等。
PostgreSQL也支持该函数, 截取的东西比Oracle的多一些,但是不支持时区时,时区分和时区的截取(文档中说是支持的,但是我的实际测试中不支持)。

Oracle EXTRACT

SQL> select extract(year from date'2011-05-17') year from dual;

      YEAR
----------
      2011

SQL> select extract(month from date'2011-05-17')  from dual;

EXTRACT(MONTHFROMDATE'2011-05-17')
----------------------------------
                                 5

SQL> select extract(day from date'2011-05-17')  from dual;

EXTRACT(DAYFROMDATE'2011-05-17')
--------------------------------
                              17

SQL> select extract(hour from timestamp'2011-05-17 12:56:20.1234') AAA from dual;

       AAA
----------
        12

SQL> select extract(minute from timestamp'2011-05-17 12:56:20.1234') part from dual;

      PART
----------
        56

SQL> select extract(second from timestamp'2011-05-17 12:56:20.1234') part from dual;

      PART
----------
   20.1234

SQL> select extract(timezone_region from systimestamp) part from dual;

PART
----------------------------------------------------------------
UNKNOWN

SQL> select extract(timezone_abbr from systimestamp) part from dual;

PART
----------
UNK

SQL> select extract(timezone_hour from systimestamp) part from dual;

      PART
----------
         8

SQL> select extract(timezone_minute from systimestamp) part from dual;

      PART
----------
         0

PostgreSQL EXTRACT

postgres=# select extract(year from date'2011-05-17') part;
 part
------
 2011
(1 行记录)

postgres=# select extract(month from date'2011-05-17') part;
 part
------
    5
(1 行记录)

postgres=# select extract(day from date'2011-05-17') part;
 part
------
   17
(1 行记录)

postgres=# select extract(week from date'2011-05-17') part;
 part
------
   20
(1 行记录)

postgres=# select extract(century from date'2011-05-17') part;
 part
------
   21
(1 行记录)

postgres=# select extract(hour from '2011-05-17 12:56:20.1234'::timestamp) AAA;
 aaa
-----
  12
(1 行记录)

postgres=# select extract(minute from '2011-05-17 12:56:20.1234'::timestamp) AAA;
 aaa
-----
  56
(1 行记录)

postgres=# select extract(second from '2011-05-17 12:56:20.1234'::timestamp) AAA;
   aaa
---------
 20.1234
(1 行记录)

postgres=# select extract(microsecond from '2011-05-17 12:56:20.1234'::timestamp) AAA;
   aaa
----------
 20123400
(1 行记录)

postgres=# select extract(isodow from '2011-05-17 12:56:20.1234'::timestamp) AAA;
 aaa
-----
   2
(1 行记录)

postgres=# select extract(quarter from '2011-05-17 12:56:20.1234'::timestamp) AAA;
 aaa
-----
   2
(1 行记录)

postgres=# select extract(timezone  from '2011-05-17 12:56:20.1234'::timestamp) AAA;
错误:  不支持时间戳单位 "timezone"

postgres=# select extract(timezone_hour from '2011-05-17 12:56:20.1234'::timestamp) AAA;
错误:  不支持时间戳单位 "timezone_hour"
相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍如何基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
13天前
|
SQL 数据可视化 关系型数据库
MCP与PolarDB集成技术分析:降低SQL门槛与简化数据可视化流程的机制解析
阿里云PolarDB与MCP协议融合,打造“自然语言即分析”的新范式。通过云原生数据库与标准化AI接口协同,实现零代码、分钟级从数据到可视化洞察,打破技术壁垒,提升分析效率99%,推动企业数据能力普惠化。
89 3
|
5月前
|
Oracle 关系型数据库 数据库
【赵渝强老师】在PostgreSQL中访问Oracle
本文介绍了如何在PostgreSQL中使用oracle_fdw扩展访问Oracle数据库数据。首先需从Oracle官网下载三个Instance Client安装包并解压,设置Oracle环境变量。接着从GitHub下载oracle_fdw扩展,配置pg_config环境变量后编译安装。之后启动PostgreSQL服务器,在数据库中创建oracle_fdw扩展及外部数据库服务,建立用户映射。最后通过创建外部表实现对Oracle数据的访问。文末附有具体操作步骤与示例代码。
167 6
【赵渝强老师】在PostgreSQL中访问Oracle
|
5月前
|
SQL 关系型数据库 MySQL
凌晨2点报警群炸了:一条sql 执行200秒!搞定之后,我总结了一个慢SQL查询、定位分析解决的完整套路
凌晨2点报警群炸了:一条sql 执行200秒!搞定之后,我总结了一个慢SQL查询、定位分析解决的完整套路
凌晨2点报警群炸了:一条sql 执行200秒!搞定之后,我总结了一个慢SQL查询、定位分析解决的完整套路
|
5月前
|
SQL 算法 数据挖掘
【SQL周周练】:利用行车轨迹分析犯罪分子作案地点
【SQL破案系列】第一篇: 如果监控摄像头拍下了很多车辆的行车轨迹,那么如何利用这些行车轨迹来分析车辆运行的特征,是不是能够分析出犯罪分子“踩点”的位置
127 15
|
6月前
|
SQL 关系型数据库 MySQL
【MySQL】SQL分析的几种方法
以上就是SQL分析的几种方法。需要注意的是,这些方法并不是孤立的,而是相互关联的。在实际的SQL分析中,我们通常需要结合使用这些方法,才能找出最佳的优化策略。同时,SQL分析也需要对数据库管理系统,数据,业务需求有深入的理解,这需要时间和经验的积累。
171 12
|
6月前
|
SQL Oracle 关系型数据库
解决大小写、保留字与特殊字符问题!Oracle双引号在SQL中的特殊应用
在Oracle数据库开发中,双引号的使用是一个重要但易被忽视的细节。本文全面解析了双引号在SQL中的特殊应用场景,包括解决标识符与保留字冲突、强制保留大小写、支持特殊字符和数字开头标识符等。同时提供了最佳实践建议,帮助开发者规避常见错误,提高代码可维护性和效率。
218 6
|
7月前
|
SQL Oracle 关系型数据库
【YashanDB知识库】共享利用Python脚本解决Oracle的SQL脚本@@用法
【YashanDB知识库】共享利用Python脚本解决Oracle的SQL脚本@@用法
|
7月前
|
SQL Oracle 关系型数据库
【YashanDB知识库】共享利用Python脚本解决Oracle的SQL脚本@@用法
本文来自YashanDB官网,介绍如何处理Oracle客户端sql*plus中使用@@调用同级目录SQL脚本的场景。崖山数据库23.2.x.100已支持@@用法,但旧版本可通过Python脚本批量重写SQL文件,将@@替换为绝对路径。文章通过Oracle示例展示了具体用法,并提供Python脚本实现自动化处理,最后调整批处理脚本以适配YashanDB运行环境。
|
4月前
|
存储 关系型数据库 测试技术
拯救海量数据:PostgreSQL分区表性能优化实战手册(附压测对比)
本文深入解析PostgreSQL分区表的核心原理与优化策略,涵盖性能痛点、实战案例及压测对比。首先阐述分区表作为继承表+路由规则的逻辑封装,分析分区裁剪失效、全局索引膨胀和VACUUM堆积三大性能杀手,并通过电商订单表崩溃事件说明旧分区维护的重要性。接着提出四维设计法优化分区策略,包括时间范围分区黄金法则与自动化维护体系。同时对比局部索引与全局索引性能,展示后者在特定场景下的优势。进一步探讨并行查询优化、冷热数据分层存储及故障复盘,解决分区锁竞争问题。
435 2
|
关系型数据库 分布式数据库 PolarDB
《阿里云产品手册2022-2023 版》——PolarDB for PostgreSQL
《阿里云产品手册2022-2023 版》——PolarDB for PostgreSQL
511 0

热门文章

最新文章

推荐镜像

更多