PostgreSQL Oracle 兼容性之 - ASCIISTR

简介:

背景

在Oracle中有一个函数asciistr,可以将非ASCII字符转换成UTF-16编码的字符,因此转换后的字符串可以存储在只支持ASCII编码的数据库中。

ASCIISTR takes as its argument a string, or an expression that resolves to a string, in any character set and returns an ASCII version of the string in the database character set.

Non-ASCII characters are converted to the form \xxxx, where xxxx represents a UTF-16 code unit.

例子

SELECT ASCIISTR('ABÄCDE') FROM DUAL;

ASCIISTR('
----------
AB\00C4CDE

\00C4即转换后的UTF-16编码,这样整个字符串就可以存储在ASCII编码的数据库中了。

PostgreSQL ASCIISTR

了解了ASCIISTR的目的之后,我们就可以在PostgreSQL中实现对非ASCII编码的字符转换了。

PostgreSQL数据库没有UTF-16字符集,但是它支持UTF-8,UTF-8是变长字符集,支持全球所有的语言字符编码。

PostgreSQL提供了几个转换函数如下

postgres=# \df convert*
                              List of functions
   Schema   |     Name     | Result data type | Argument data types |  Type  
------------+--------------+------------------+---------------------+--------
 pg_catalog | convert      | bytea            | bytea, name, name   | normal
 pg_catalog | convert_from | text             | bytea, name         | normal
 pg_catalog | convert_to   | bytea            | text, name          | normal
(3 rows)

例子,支持来回转换

postgres=# select convert_to('abc你好中国cde','UTF8');
               convert_to               
----------------------------------------
 \x616263e4bda0e5a5bde4b8ade59bbd636465
(1 row)

postgres=# select convert_from(convert_to('abc你好中国cde','UTF8'),'UTF8');
  convert_from  
----------------
 abc你好中国cde
(1 row)

postgres=# select convert_from('\x616263e4bda0e5a5bde4b8ade59bbd636465', 'UTF8');
  convert_from  
----------------
 abc你好中国cde
(1 row)

方法2,使用textsend函数,这个函数没有编码输入,所以需要设置client_encoding。

postgres=# set client_encoding='UTF8';
SET
postgres=# select textsend('abc你好中国cde');
                textsend                
----------------------------------------
 \x616263e4bda0e5a5bde4b8ade59bbd636465
(1 row)

postgres=# set client_encoding='GBK';
SET
postgres=# select textsend('abc你好中国cde');
ERROR:  character with byte sequence 0xad 0xe5 in encoding "GBK" has no equivalent in encoding "UTF8"
LOCATION:  report_untranslatable_char, wchar.c:2051
postgres=# select textsend('abc你好cde');
          textsend          
----------------------------
 \x616263e4bda0e5a5bd636465
(1 row)

PostgreSQL支持的字符编码转换函数在这里

postgres=# select * from pg_conversion ;
            conname             | connamespace | conowner | conforencoding | contoencoding |            conproc             | condefault 
--------------------------------+--------------+----------+----------------+---------------+--------------------------------+------------
 ascii_to_mic                   |           11 |       10 |              0 |             7 | ascii_to_mic                   | t
 mic_to_ascii                   |           11 |       10 |              7 |             0 | mic_to_ascii                   | t
......
 utf8_to_shift_jis_2004         |           11 |       10 |              6 |            41 | utf8_to_shift_jis_2004         | t
 euc_jis_2004_to_shift_jis_2004 |           11 |       10 |              5 |            41 | euc_jis_2004_to_shift_jis_2004 | t
 shift_jis_2004_to_euc_jis_2004 |           11 |       10 |             41 |             5 | shift_jis_2004_to_euc_jis_2004 | t
(132 rows)

以上例子把整个字符串都进行了转换,包括一些已经是ASCII的字符也被转换了,转换后长度变长了,如果你要尽量缩小长度怎么办呢?

如果你要对一个字符串中非ASCII字符转换为bytea,而ASCII字符保持不变,则需要自定义PostgreSQL函数,如下demo

create or replace function asciistr(str text, encoding text) returns text[] as $$
declare
  mid text;
  res text[] := (array[])::text[];
begin
  foreach mid in array regexp_split_to_array(str, '')
  loop
    if ascii(mid)<256 then
      res := array_append(res, mid);
    else
      res := array_append(res, (convert_to(mid,encoding))::text);
    end if;
  end loop;
  return res;
end;
$$
language plpgsql strict;

测试

postgres=# select asciistr('abc中国你好ced', 'UTF8');
                           asciistr                            
---------------------------------------------------------------
 {a,b,c,"\\xe4b8ad","\\xe59bbd","\\xe4bda0","\\xe5a5bd",c,e,d}
(1 row)

你还可以输出字符串,也可以直接输出字符串

postgres=# select array_to_string(asciistr('abc中国你好ced', 'UTF8'), '');
            array_to_string             
----------------------------------------
 abc\xe4b8ad\xe59bbd\xe4bda0\xe5a5bdced
(1 row)

使用这种方法,在反转换时,也要通过函数来处理。

create or replace function reverse_asciistr(str text[], encoding text) returns text as $$
declare
  mid text;
  res text := '';
begin
  foreach mid in array str
  loop
    if mid ~ '^\\x' then
      res := concat(res, convert_from(mid::bytea, encoding));
    else
      res := concat(res, mid);
    end if;
  end loop;
  return res;
end;
$$
language plpgsql strict;

反转转换举例

postgres=# select reverse_asciistr(asciistr('abc_12\ab你好\ade中国_1jjr3', 'UTF8'), 'UTF8');
      reverse_asciistr       
-----------------------------
 abc_12\ab你好\ade中国_1jjr3
(1 row)

参考

https://www.postgresql.org/docs/9.6/static/multibyte.html

Count

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍如何基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
7月前
|
Oracle 关系型数据库 数据库
【赵渝强老师】在PostgreSQL中访问Oracle
本文介绍了如何在PostgreSQL中使用oracle_fdw扩展访问Oracle数据库数据。首先需从Oracle官网下载三个Instance Client安装包并解压,设置Oracle环境变量。接着从GitHub下载oracle_fdw扩展,配置pg_config环境变量后编译安装。之后启动PostgreSQL服务器,在数据库中创建oracle_fdw扩展及外部数据库服务,建立用户映射。最后通过创建外部表实现对Oracle数据的访问。文末附有具体操作步骤与示例代码。
269 6
【赵渝强老师】在PostgreSQL中访问Oracle
|
9月前
|
SQL Oracle 关系型数据库
|
11月前
|
SQL 存储 Oracle
【YashanDB观点】论Oracle兼容性,我们需要做什么
我们经常发现,部分国产数据库声称与 Oracle兼容性高达90%,但在实际迁移过程中,仍需要频繁地修改业务应用的代码。为何实现与Oracle高兼容度的数据库产品如此困难?其中一个重要原因是Oracle兼容性不仅是模仿,而是一个非常复杂和工程量庞大的逆向工程。其技术实现的复杂性以及多如牛毛的细节,足以让多数“年轻”的数据库团队望洋兴叹。YashanDB作为一款从核心理论到关键系统均为原创的数据库产品,从构建初期就具备了技术优势,在Oracle兼容性实现上,敢于亮剑并充分发挥工匠精神,不断打磨,努力构筑一个真正形神兼备的数据库产品。以下将从YashanDB SQL引擎技术、Oracle兼容性的开发
|
11月前
|
SQL 存储 Oracle
【YashanDB观点】论Oracle兼容性,我们需要做什么
Oracle兼容性是目前国产数据库的关键任务之一,其直接影响到商业迁移的成本和竞争力。
221 8
|
Oracle NoSQL 关系型数据库
主流数据库对比:MySQL、PostgreSQL、Oracle和Redis的优缺点分析
主流数据库对比:MySQL、PostgreSQL、Oracle和Redis的优缺点分析
2606 3
|
人工智能 Oracle 关系型数据库
一篇文章弄懂Oracle和PostgreSQL的Database Link
一篇文章弄懂Oracle和PostgreSQL的Database Link
|
SQL Oracle 关系型数据库
常用数据库的分页语句(mySQL、oracle、PostgreSQL、SQL Server)
常用数据库的分页语句(mySQL、oracle、PostgreSQL、SQL Server)
|
存储 Oracle 关系型数据库
PolarDB 开源版通过orafce支持Oracle兼容性
背景PolarDB 的云原生存算分离架构, 具备低廉的数据存储、高效扩展弹性、高速多机并行计算能力、高速数据搜索和处理; PolarDB与计算算法结合, 将实现双剑合璧, 推动业务数据的价值产出, 将数据变成生产力.本文将介绍PolarDB开源版通过orafce支持Oracle兼容性 .测试环境为m...
340 0
|
3月前
|
Oracle 关系型数据库 Linux
【赵渝强老师】Oracle数据库配置助手:DBCA
Oracle数据库配置助手(DBCA)是用于创建和配置Oracle数据库的工具,支持图形界面和静默执行模式。本文介绍了使用DBCA在Linux环境下创建数据库的完整步骤,包括选择数据库操作类型、配置存储与网络选项、设置管理密码等,并提供了界面截图与视频讲解,帮助用户快速掌握数据库创建流程。
390 93
|
2月前
|
Oracle 关系型数据库 Linux
【赵渝强老师】使用NetManager创建Oracle数据库的监听器
Oracle NetManager是数据库网络配置工具,用于创建监听器、配置服务命名与网络连接,支持多数据库共享监听,确保客户端与服务器通信顺畅。
225 0

相关产品

  • 云原生数据库 PolarDB
  • 云数据库 RDS PostgreSQL 版
  • 推荐镜像

    更多