《卸甲笔记》-PostgreSQL和Oracle的SQL差异分析之四:特殊字符和符号

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

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

空字符串( '' )

Oracle中,空字符串( '' )很多时候是和null同样处理的。给varchar2和char类型赋值的时候按照null处理。在给日期类型或者数字类型赋值的时候,也是按照null处理。但是在where条件部分,=‘’和 is null 是不同的。

PostgreSQL里面,空字符串( '' )和 null是不同的。完全是不同的处理。转换SQL的时候,一定要注意。

Oracle 空字符串
SQL> create table o_test(value1 number, value2 varchar2(10), value3 date);

表已创建。

SQL> insert into o_test values('', '11111', to_date( '2010-01-01','YYYY-MM-DD'));

已创建 1 行。

SQL> insert into o_test values(1, '', to_date( '2010-01-01','YYYY-MM-DD'));

已创建 1 行。

SQL> insert into o_test values(2, '22222', to_date( '','YYYY-MM-DD'));

已创建 1 行。

SQL> select * from o_test;

    VALUE1 VALUE2     VALUE3
---------- ---------- --------------
           11111      01-1月 -10
         1            01-1月 -10
         2 22222

SQL> select * from o_test where value1 = '';

未选定行

SQL> select * from o_test where value1 is null;

    VALUE1 VALUE2     VALUE3
---------- ---------- --------------
           11111      01-1月 -10

SQL> select * from o_test where value2 = '';

未选定行

SQL> select * from o_test where value2 is null;

    VALUE1 VALUE2     VALUE3
---------- ---------- --------------
         1            01-1月 -10

SQL> select * from o_test where value3 = '';

未选定行

SQL> select * from o_test where value3 is null;

    VALUE1 VALUE2     VALUE3
---------- ---------- --------------
         2 22222
PostgreSQL 空字符串
postgres=# create table p_test(value1 integer, value2 varchar(10), value3 timestamp(0) without time zone);
CREATE TABLE
postgres=# insert into p_test values('', '11111', to_timestamp('2010-01-01', 'YYYY-MM-DD'));
错误:  无效的整数类型输入语法: ""
第1行insert into p_test values('', '11111', to_timestamp('2010-01...
                               ^
postgres=#  insert into p_test values(null, '11111', to_timestamp('2010-01-01', 'YYYY-MM-DD'));
INSERT 0 1
postgres=# insert into p_test values(1, '', to_timestamp('2010-01-01', 'YYYY-MM-DD'));
INSERT 0 1
postgres=# insert into p_test values(2, '22222', to_timestamp('', 'YYYY-MM-DD'));
INSERT 0 1
postgres=# select * from p_test;
 value1 | value2 |         value3
--------+--------+------------------------
        | 11111  | 2010-01-01 00:00:00
      1 |        | 2010-01-01 00:00:00
      2 | 22222  | 0001-01-01 00:00:00 BC
(3 行记录)

postgres=# select * from p_test where value1 = '';
错误:  无效的整数类型输入语法: ""
第1行select * from p_test where value1 = '';
                                         ^

postgres=# select * from p_test where value1 is null;
 value1 | value2 |       value3
--------+--------+---------------------
        | 11111  | 2010-01-01 00:00:00
(1 行记录)

postgres=# select * from p_test where value2 =  '';
 value1 | value2 |       value3
--------+--------+---------------------
      1 |        | 2010-01-01 00:00:00
(1 行记录)

postgres=# select * from p_test where value2 is null;
 value1 | value2 | value3
--------+--------+--------
(0 行记录)

postgres=# select * from p_test where value3 is null;
 value1 | value2 | value3
--------+--------+--------
(0 行记录)

postgres=# select * from p_test where to_char(value3, 'YYYY-MM-DD') ='0001-01-01';
 value1 | value2 |         value3
--------+--------+------------------------
      2 | 22222  | 0001-01-01 00:00:00 BC
(1 行记录)

比较运算符

Oracle中,比较运算符之间是可以有空格的。比如【> = 】这样的写法是允许的。而PostgreSQL中,运算符之间不能有空格。

Oracle 比较运算符
SQL> select * from o_test where value1 > = 2;

    VALUE1 VALUE2     VALUE3
---------- ---------- --------------
         2 22222

SQL> select * from o_test where value1 <                         = 3;

    VALUE1 VALUE2     VALUE3
---------- ---------- --------------
         1            01-1月 -10
         2 22222
PostgreSQL 比较运算符
postgres=# select * from p_test where value1 > = 2;
错误:  语法错误 在 "=" 或附近的
第1行select * from p_test where value1 > = 2;
                                         ^
postgres=# select * from p_test where value1 >= 2;
 value1 | value2 |         value3
--------+--------+------------------------
      2 | 22222  | 0001-01-01 00:00:00 BC
(1 行记录)

postgres=# select * from p_test where value1 < = 3;
错误:  语法错误 在 "=" 或附近的
第1行select * from p_test where value1 < = 3;
                                         ^
postgres=# select * from p_test where value1 <= 3;
 value1 | value2 |         value3
--------+--------+------------------------
      1 |        | 2010-01-01 00:00:00
      2 | 22222  | 0001-01-01 00:00:00 BC
(2 行记录)

逃逸字符

逃逸的意思是有特殊意义的字符,前面如果加上逃逸字符的话,就不代表它的特殊含义,而代表它的字符本意。
Oracle的SQL中,使用( ' )来逃逸它本身。Oracle没有其它的标准逃逸字符。比如"n"并不代表回车,而是代表它的本意的"n"两个字符。如果输入回车的话,使用chr(10)来表示。在正则表达式等需要使用特殊字符本意的时候,使用关键字(escape)后面定义的字符进行逃逸。

PostgreSQL的SQL,也支持使用( ' )来逃逸它本身。老版的还支持使用反斜杠( ), 但新版已经不使用。Oracle定义了标准的逃逸字串(E'XXX') 格式。 在正则表达式等需要使用特殊字符本意的时候,默认使用""做逃逸字串。也可以使用关键字(escape)后面定义的字符进行逃逸。

数据迁移的时候,老版的PostgreSQL中,需要对逃逸字串进行特殊处理。比如把"“替换成"\\"。新版已经不再需要。可以直接按照Oracle的方式直接转换。

Oracle 逃逸字符
SQL> insert into o_test values(1, '12e34'6r8', null);
ERROR:
ORA-01756: 引号内的字符串没有正确结束

SQL> insert into o_test values(1, '12e34''6r8', null);

已创建 1 行。

SQL> insert into o_test values(1, '12e34\n6r8', null);

已创建 1 行。

SQL> insert into o_test values(1, '12e34' || chr(10) || '6r8', null);

已创建 1 行。

SQL> select * from o_test;

    VALUE1 VALUE2     VALUE3
---------- ---------- --------------
         1 1234_678
         1 12e34%6r8
         1 12e34'6r8
         1 12e34\n6r8
         1 12e34
           6r8

SQL> select * from o_test where value2 like '%_%';

    VALUE1 VALUE2     VALUE3
---------- ---------- --------------
         1 1234_678
         1 12e34%6r8
         1 12e34'6r8
         1 12e34\n6r8
         1 12e34
           6r8

SQL> select * from o_test where value2 like '%\_%';

    VALUE1 VALUE2     VALUE3
---------- ---------- --------------
         1 12e34\n6r8

SQL> select * from o_test where value2 like '%\_%' escape '\' ;

    VALUE1 VALUE2     VALUE3
---------- ---------- --------------
         1 1234_678

SQL> select * from o_test where value2 like '%r_%' escape 'r' ;

    VALUE1 VALUE2     VALUE3
---------- ---------- --------------
         1 1234_678
PostgreSQL 逃逸字符
postgres=#  insert into p_test values(1, '12e34'6r8', null);
postgres'# ');
错误:  语法错误 在 "6" 或附近的
第1行insert into p_test values(1, '12e34'6r8', null);
                                         ^
postgres=#  insert into p_test values(1, '12e34''6r8', null);
INSERT 0 1
postgres=#  insert into p_test values(1, '\n\r', null);
INSERT 0 1
postgres=# insert into p_test values(1, E'ab\n\rc', null);
INSERT 0 1
postgres=# insert into p_test values(1, 'ab'|| chr(10) || 'c', null);
INSERT 0 1
postgres=# select * from p_test;
 value1 |  value2   | value3
--------+-----------+--------
      1 | 1234_678  |
      1 | 12e34%6r8 |
      1 | 12e34'6r8 |
      1 | \n\r      |
      1 | ab       +|
        | \rc       |
      1 | ab       +|
        | c         |
(6 行记录)

postgres=# select * from p_test where value2 like '%_%';
 value1 |  value2   | value3
--------+-----------+--------
      1 | 1234_678  |
      1 | 12e34%6r8 |
      1 | 12e34'6r8 |
      1 | \n\r      |
      1 | ab       +|
        | \rc       |
      1 | ab       +|
        | c         |
(6 行记录)

postgres=# select * from p_test where value2 like '%\_%';
 value1 |  value2  | value3
--------+----------+--------
      1 | 1234_678 |
(1 行记录)

postgres=# select * from p_test where value2 like '%r_%' escape 'r' ;
 value1 |  value2  | value3
--------+----------+--------
      1 | 1234_678 |
(1 行记录)

postgres=# select * from p_test where value2 like '%\\%';
 value1 | value2 | value3
--------+--------+--------
      1 | \n\r   |
(1 行记录)

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
11天前
|
Oracle NoSQL 关系型数据库
主流数据库对比:MySQL、PostgreSQL、Oracle和Redis的优缺点分析
主流数据库对比:MySQL、PostgreSQL、Oracle和Redis的优缺点分析
38 2
|
27天前
|
SQL 数据采集 存储
SQL server 特殊字符"\u0000"处理
【9月更文挑战第12天】在 SQL Server 中,空字符 `\u0000` 可能导致数据处理问题。解决方法包括:1) 查找包含该字符的数据,使用 `LIKE &#39;%\u0000%&#39;` 进行查询;2) 替换该字符,使用 `REPLACE` 函数将其替换为空或其他字符;3) 在应用程序中验证和清理输入数据,防止其插入数据库;4) 注意数据类型、索引性能及数据库设计,确保数据质量和可靠性。
|
2月前
|
SQL 关系型数据库 数据处理
|
2月前
|
SQL 数据处理 数据库
SQL正则表达式应用:文本数据处理的强大工具——深入探讨数据验证、模式搜索、字符替换等核心功能及性能优化和兼容性问题
【8月更文挑战第31天】SQL正则表达式是数据库管理和应用开发中处理文本数据的强大工具,支持数据验证、模式搜索和字符替换等功能。本文通过问答形式介绍了其基本概念、使用方法及注意事项,帮助读者掌握这一重要技能,提升文本数据处理效率。尽管功能强大,但在不同数据库系统中可能存在兼容性问题,需谨慎使用以优化性能。
36 0
|
2月前
|
SQL 关系型数据库 MySQL
SQL Server、MySQL、PostgreSQL:主流数据库SQL语法异同比较——深入探讨数据类型、分页查询、表创建与数据插入、函数和索引等关键语法差异,为跨数据库开发提供实用指导
【8月更文挑战第31天】SQL Server、MySQL和PostgreSQL是当今最流行的关系型数据库管理系统,均使用SQL作为查询语言,但在语法和功能实现上存在差异。本文将比较它们在数据类型、分页查询、创建和插入数据以及函数和索引等方面的异同,帮助开发者更好地理解和使用这些数据库。尽管它们共用SQL语言,但每个系统都有独特的语法规则,了解这些差异有助于提升开发效率和项目成功率。
164 0
|
3月前
|
SQL Oracle 关系型数据库
|
3月前
|
SQL Oracle 关系型数据库
MySQL、SQL Server和Oracle数据库安装部署教程
数据库的安装部署教程因不同的数据库管理系统(DBMS)而异,以下将以MySQL、SQL Server和Oracle为例,分别概述其安装部署的基本步骤。请注意,由于软件版本和操作系统的不同,具体步骤可能会有所变化。
185 3
|
2月前
|
SQL 存储 关系型数据库
运维笔记.MySQL.基于mysqldump数据备份与恢复
运维笔记.MySQL.基于mysqldump数据备份与恢复
42 0
|
2月前
|
SQL 关系型数据库 MySQL
【go笔记】使用sqlx操作MySQL
【go笔记】使用sqlx操作MySQL
|
4月前
|
存储 关系型数据库 MySQL
Mysql优化之索引相关介绍(笔记)
索引查找从顶层节点开始查找,通过key值,也就是主键的值进行比较,最终定位到存储数据的叶子节点上面,从叶子节点取出响应的数据。
54 0
Mysql优化之索引相关介绍(笔记)

推荐镜像

更多