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

简介: PostgreSQL是世界上功能最强大的开源数据库,在国内得到了越来越多机构和开发者的青睐和应用。随着PostgreSQL的应用越来越广泛,Oracle向PostgreSQL数据库的数据迁移需求也越来越多。数据库之间数据迁移的时候,首先是迁移数据,然后就是SQL、存储过程、序列等程序中不同的数据库.

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

1、to_number函数

to_number用于将字符类型转换成数字。主要使用在显示格式的控制以及排序等地方。特别是排序的时候,因为按照字符排序和按照数字排序,结果是不同的。

Oracle的to_number函数接受两个参数。第一个参数是需要转换的字符串,第二个参数是要转换的格式。实际使用的时候,除非采用特殊的格式显示,否则一个参数就已经足够了。

PostgreSQL的to_number函数也接受两个参数。使用的时候,不能只使用一个参数。排序的时候, 格式字符串中需要设置转换的位数为该字段的最大位数。否则,只使用格式提供的转换位数来排序。比如格式提供了两位,那么就转换最前面的两位字符为数字,然后使用它来排序。

Oracle to_number函数

SQL> desc o_test;
 名称                                      是否为空? 类型
 ----------------------------------------- -------- ----------------------------
 ID                                                 NUMBER
 NAME                                               VARCHAR2(10)
 AGE                                                VARCHAR2(10)

SQL> select * from o_test;

        ID NAME       AGE
---------- ---------- ----------
           赵大       20
           钱二       9
           孙三       30
           李四       110

SQL> select * from o_test order by age;

        ID NAME       AGE
---------- ---------- ----------
           李四       110
           赵大       20
           孙三       30
           钱二       9

SQL> select * from o_test order by to_number(age);

        ID NAME       AGE
---------- ---------- ----------
           钱二       9
           赵大       20
           孙三       30
           李四       110

SQL> select id, name, to_number(age) age from o_test order by to_number(age);

        ID NAME              AGE
---------- ---------- ----------
           钱二                9
           赵大               20
           孙三               30
           李四              110

PostgreSQL to_number函数

postgres=# \d p_test;
                           数据表 "public.p_test"
 栏位 |         类型          |                    修饰词
------+-----------------------+----------------------------------------------
 id   | integer               | 非空 默认 nextval('p_test_id_seq'::regclass)
 name | character varying(10) |
 age  | character varying(10) |

postgres=# select * from p_test;
 id | name | age
----+------+-----
  1 | 赵大 | 20
  2 | 钱二 | 9
  3 | 孙三 | 30
  4 | 李四 | 110
(4 行记录)

postgres=# select * from p_test order by age;
 id | name | age
----+------+-----
  4 | 李四 | 110
  1 | 赵大 | 20
  3 | 孙三 | 30
  2 | 钱二 | 9
(4 行记录)

postgres=# select * from p_test order by to_number(age);
错误:  函数 to_number(character varying) 不存在
第1行select * from p_test order by to_number(age);
                                   ^
提示:  没有匹配指定名称和参数类型的函数. 您也许需要增加明确的类型转换.
postgres=# select * from p_test order by to_number(age,'9999999999');
 id | name | age
----+------+-----
  2 | 钱二 | 9
  1 | 赵大 | 20
  3 | 孙三 | 30
  4 | 李四 | 110
(4 行记录)

postgres=# select * from p_test order by to_number(age,'99');
 id | name | age
----+------+-----
  2 | 钱二 | 9
  4 | 李四 | 110
  1 | 赵大 | 20
  3 | 孙三 | 30
(4 行记录)

postgres=# select id,name, to_number(age,'9999999999') from p_test order by to_number(age,'9999999999');
 id | name | to_number
----+------+-----------
  2 | 钱二 |         9
  1 | 赵大 |        20
  3 | 孙三 |        30
  4 | 李四 |       110
(4 行记录)

2、decode函数

decode是Oracle固有的一个函数,用于条件判断。其格式为
decode(条件, 值1, 返回值1, 值2, 返回值2,... 值n, 返回值n, 缺省值) 。当条件等于值1的时候返回返回值1,······等于值n的时候返回返回值n。都不等于的时候返回缺省值。

PostgreSQL中,decode函数使用来解码的,和encode函数相对。对于Oracle的decode函数,可以把它转换成case......when....的SQL语句,得到一样的效果。
Oracle也支持case....when。用法和PostgreSQL中类似。

Oracle

SQL> select * from o_test;

        ID NAME       AGE
---------- ---------- ----------
           赵大       20
           钱二       9
           孙三       30
           李四       110

SQL> select decode(age, '20', '赵大', '9', '钱二', '张三') testname from o_test;

TEST
----
赵大
钱二
张三
张三

SQL> select case age when '20' then '赵大' when '9' then '钱二' else '张三' end testname from o_test;

TEST
----
赵大
钱二
张三
张三

SQL> select case  when age = '20' then '赵大' when age= '9' then '钱二' else '张三' end testname from o_test;

TEST
----
赵大
钱二
张三
张三

PostgreSQL

postgres=# select * from p_test;
 id | name | age
----+------+-----
  1 | 赵大 | 20
  2 | 钱二 | 9
  3 | 孙三 | 30
  4 | 李四 | 110
(4 行记录)

postgres=#  select case age when '20' then '赵大' when '9' then '钱二' else '张三' end testname from p_test;
 testname
----------
 赵大
 钱二
 张三
 张三
(4 行记录)


postgres=#  select case when age='20' then '赵大' when age= '9' then '钱二' else '张三' end testname from p_test;
 testname
----------
 赵大
 钱二
 张三
 张三
(4 行记录)

postgres=# select encode('abcdefghijklmn', 'base64');
        encode
----------------------
 YWJjZGVmZ2hpamtsbW4=
(1 行记录)

postgres=# select decode('YWJjZGVmZ2hpamtsbW4=', 'base64');
             decode
--------------------------------
 \x6162636465666768696a6b6c6d6e
(1 行记录)

3、instr函数

Oracle的instr函数是查找一个字符串中,另一个字符串所在的位置。如果找不到则返回0。instr一共有四个参数。前两个分别表示源字符串和查找字符串,第三个表示开始位置(<0的时候表示从右望左找)。第四个表示第几次出现的值。
PostgreSQL中,可以使用position(substring in string) 函数来对应它。position函数没有Oracle的那么复杂,有些复杂的功能只能使用自定义函数来实现它。

Oracle instr

SQL> select instr('helloworld', 'l') from dual;

INSTR('HELLOWORLD','L')
-----------------------
                      3

SQL> select instr('helloworld', 'l', 5) from dual;

INSTR('HELLOWORLD','L',5)
-------------------------
                        9

SQL> select instr('helloworld', 'l', -5) from dual;

INSTR('HELLOWORLD','L',-5)
--------------------------
                         4

SQL> select instr('helloworld', 'l', 4, 2) from dual;

INSTR('HELLOWORLD','L',4,2)
---------------------------
                          9

PostgreSQL position

postgres=# select position('l' in 'helloworld');
 position
----------
        3
(1 行记录)

postgres=# select length(substring('helloworld', 1, 4)) + position('l' in substring('helloworld',5));
 ?column?
----------
        9
(1 行记录)

postgres=#  select instr('helloworld', 'l', -5, 1) ;
错误:  函数 instr(unknown, unknown, integer, integer) 不存在
第1行select instr('helloworld', 'l', -5, 1) ;
            ^
提示:  没有匹配指定名称和参数类型的函数. 您也许需要增加明确的类型转换.
postgres=# CREATE FUNCTION instr(string varchar, string_to_search varchar,
postgres(# beg_index integer, occur_index integer)
postgres-# RETURNS integer AS 
$$

postgres$# DECLARE
postgres$# pos integer NOT NULL DEFAULT 0;
postgres$# occur_number integer NOT NULL DEFAULT 0;
postgres$# temp_str varchar;
postgres$# beg integer;
postgres$# i integer;
postgres$# length integer;
postgres$# ss_length integer;
postgres$# BEGIN
postgres$# IF beg_index > 0 THEN
postgres$# beg := beg_index;
postgres$# temp_str := substring(string FROM beg_index);
postgres$#   FOR i IN 1..occur_index LOOP
postgres$# pos := position(string_to_search IN temp_str);
postgres$#             IF i = 1 THEN
postgres$# beg := beg + pos - 1;
postgres$# ELSE
postgres$# beg := beg + pos;
postgres$# END IF;
postgres$#             temp_str := substring(string FROM beg + 1);
postgres$# END LOOP;
postgres$#         IF pos = 0 THEN
postgres$# RETURN 0;
postgres$# ELSE
postgres$# RETURN beg;
postgres$# END IF;
postgres$# ELSE
postgres$# ss_length := char_length(string_to_search);
postgres$# length := char_length(string);
postgres$# beg := length + beg_index - ss_length + 2;
postgres$#         WHILE beg > 0 LOOP
postgres$# temp_str := substring(string FROM beg FOR ss_length);
postgres$# pos := position(string_to_search IN temp_str);
postgres$#             IF pos > 0 THEN
postgres$# occur_number := occur_number + 1;
postgres$#                 IF occur_number = occur_index THEN
postgres$# RETURN beg;
postgres$# END IF;
postgres$# END IF;
postgres$#             beg := beg - 1;
postgres$# END LOOP;
postgres$#         RETURN 0;
postgres$# END IF;
postgres$#
postgres$# END;
postgres$# 
$$
 LANGUAGE plpgsql;
CREATE FUNCTION
postgres=#  select instr('helloworld', 'l', -5, 1) ;
 instr
-------
     4
(1 行记录)

postgres=# select instr('helloworld', 'l', 4, 2);
 instr
-------
     9
(1 行记录)
相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍如何基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
SQL 数据可视化 关系型数据库
MCP与PolarDB集成技术分析:降低SQL门槛与简化数据可视化流程的机制解析
阿里云PolarDB与MCP协议融合,打造“自然语言即分析”的新范式。通过云原生数据库与标准化AI接口协同,实现零代码、分钟级从数据到可视化洞察,打破技术壁垒,提升分析效率99%,推动企业数据能力普惠化。
1028 3
|
关系型数据库 MySQL 数据库
阿里云数据库RDS费用价格:MySQL、SQL Server、PostgreSQL和MariaDB引擎收费标准
阿里云RDS数据库支持MySQL、SQL Server、PostgreSQL、MariaDB,多种引擎优惠上线!MySQL倚天版88元/年,SQL Server 2核4G仅299元/年,PostgreSQL 227元/年起。高可用、可弹性伸缩,安全稳定。详情见官网活动页。
1939 152
|
关系型数据库 MySQL 数据库
阿里云数据库RDS支持MySQL、SQL Server、PostgreSQL和MariaDB引擎
阿里云数据库RDS支持MySQL、SQL Server、PostgreSQL和MariaDB引擎,提供高性价比、稳定安全的云数据库服务,适用于多种行业与业务场景。
1332 156
|
SQL 关系型数据库 MySQL
Go语言数据库编程:使用 `database/sql` 与 MySQL/PostgreSQL
Go语言通过`database/sql`标准库提供统一数据库操作接口,支持MySQL、PostgreSQL等多种数据库。本文介绍了驱动安装、连接数据库、基本增删改查操作、预处理语句、事务处理及错误管理等内容,涵盖实际开发中常用的技巧与注意事项,适合快速掌握Go语言数据库编程基础。
1809 213
|
关系型数据库 分布式数据库 数据库
阿里云数据库收费价格:MySQL、PostgreSQL、SQL Server和MariaDB引擎费用整理
阿里云数据库提供多种类型,包括关系型与NoSQL,主流如PolarDB、RDS MySQL/PostgreSQL、Redis等。价格低至21元/月起,支持按需付费与优惠套餐,适用于各类应用场景。
|
SQL Oracle 关系型数据库
Oracle数据库创建表空间和索引的SQL语法示例
以上SQL语法提供了一种标准方式去组织Oracle数据库内部结构,并且通过合理使用可以显著改善查询速度及整体性能。需要注意,在实际应用过程当中应该根据具体业务需求、系统资源状况以及预期目标去合理规划并调整参数设置以达到最佳效果。
802 8
|
Oracle 关系型数据库 数据库
【赵渝强老师】在PostgreSQL中访问Oracle
本文介绍了如何在PostgreSQL中使用oracle_fdw扩展访问Oracle数据库数据。首先需从Oracle官网下载三个Instance Client安装包并解压,设置Oracle环境变量。接着从GitHub下载oracle_fdw扩展,配置pg_config环境变量后编译安装。之后启动PostgreSQL服务器,在数据库中创建oracle_fdw扩展及外部数据库服务,建立用户映射。最后通过创建外部表实现对Oracle数据的访问。文末附有具体操作步骤与示例代码。
1587 6
【赵渝强老师】在PostgreSQL中访问Oracle
|
SQL 关系型数据库 MySQL
凌晨2点报警群炸了:一条sql 执行200秒!搞定之后,我总结了一个慢SQL查询、定位分析解决的完整套路
凌晨2点报警群炸了:一条sql 执行200秒!搞定之后,我总结了一个慢SQL查询、定位分析解决的完整套路
凌晨2点报警群炸了:一条sql 执行200秒!搞定之后,我总结了一个慢SQL查询、定位分析解决的完整套路
|
SQL 关系型数据库 PostgreSQL
CTE vs 子查询:深入拆解PostgreSQL复杂SQL的隐藏性能差异
本文深入探讨了PostgreSQL中CTE(公共表表达式)与子查询的选择对SQL性能的影响。通过分析两者底层机制,揭示CTE的物化特性及子查询的优化融合优势,并结合多场景案例对比执行效率。最终给出决策指南,帮助开发者根据数据量、引用次数和复杂度选择最优方案,同时提供高级优化技巧和版本演进建议,助力SQL性能调优。
|
SQL 算法 数据挖掘
【SQL周周练】:利用行车轨迹分析犯罪分子作案地点
【SQL破案系列】第一篇: 如果监控摄像头拍下了很多车辆的行车轨迹,那么如何利用这些行车轨迹来分析车辆运行的特征,是不是能够分析出犯罪分子“踩点”的位置
486 15

推荐镜像

更多