《卸甲笔记》-PostgreSQL和Oracle的数据类型的对比系列一:字符类型

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

PostgreSQL是世界上功能最强大的开源数据库,在国内得到了越来越多机构和开发者的青睐和应用。随着PostgreSQL的应用越来越广泛,Oracle向PostgreSQL数据库的数据迁移需求也越来越多。数据库之间数据迁移的时候,首先遇到的,并且也是最重要的,就是数据类型之间的转换。下面根据自己的理解和测试,写了一些数据类型之间的差异以及迁移时的注意事项的文章,不足之处,尚请多多指教。

字符类型

大家知道,Oracle有四种字符类型,分别是char,varchar2,nchar,nvarchar2。而PostgreSQL只有两种字符类型,分别是character (char)和 character varying(varchar)。它们之间的有什么异同呢?

1、数据最小单位

Oracle:char和varchar2的数据最小单位,默认值为BYTE,即字节数。可以修改为CHAR,则为字符。通过参数NLS_LENGTH_SEMANTICS来控制。
而Oracle的nchar和nvarchar2是针对特定字符集来的,数据最小单位根据字符集不同而不同。如字符集是AL16UTF16,就是2个字节,而字符集是UTF8,就是3个,通过参数NLS_NCHAR_CHARACTERSET来控制(我的Oracle的NLS_NCHAR_CHARACTERSET值就是AL16UTF16,一个字为2byte)。
当数据不够最大长度的时候,char和nchar写入/取出的是最大长度的字符串,超出实际长度的使用空格补齐。而varchar2和 nvarchar2写入/取出的是实际操作的字符串。

SQL> create table o_test(id int primary key,
  2  name char(5),
  3  n_name nchar(5),
  4  addr varchar2(5),
  5  n_addr nvarchar2(5));

表已创建。

SQL> insert into o_test values(1, 'li',  'li', 'BJ', 'BJ');

已创建 1 行。

SQL> select lengthb(name), lengthb(n_name), lengthb(addr),lengthb(n_addr)
  2  from o_test;

LENGTHB(NAME) LENGTHB(N_NAME) LENGTHB(ADDR) LENGTHB(N_ADDR)
------------- --------------- ------------- ---------------
            5              10             2               4

PostgreSQL:char和 varchar的数据最小单位都是字符(CHAR)。
当数据不够最大长度的时候,char类型的数据物理上用空白填充到指定的长度,并且以这种方式存储和显示。但是,填充的空白是无意义的。在取出来实际使用的时候,空白会自动被删除。
VARCHAR类型的数据,会按照实际长度存储。最后的空白都是有意义的,不会被删除。

highgo=# create table p_test(id  smallint  primary key,
highgo(# name char(5),
highgo(# v_name varchar(5));
CREATE TABLE
highgo=# insert into p_test values(1,'赵 ', '赵老大 ');
INSERT 0 1
highgo=# select length(name),  length(v_name) from p_test;
 length | length
--------+--------
      1 |      4
(1 行记录)

2、数据类型的最大长度

Oracle:char类型的最大长度是2000字节,varchar2是4000个字节。
nchar,nvarchar2类型的最大长度根据数据集不同而不同。最终的byte数不能超过2000和4000。如字符集为AL16UTF16,则nchar的为2000/2=1000,而nvarchar2则为4000/2=2000

SQL> create table o_test2(name char(2001));
create table o_test2(name char(2001))
                               *
第 1 行出现错误:
ORA-00910: 指定的长度对于数据类型而言过长

SQL> create table o_test2(name char(2000));

表已创建。

SQL> create table o_test3(name varchar2(4001));
create table o_test3(name varchar2(4001))
                                  *
第 1 行出现错误:
ORA-00910: 指定的长度对于数据类型而言过长

SQL> create table o_test3(name varchar2(4000));

表已创建。

SQL> create table o_table5(name nchar(1001));
create table o_table5(name nchar(1001))
                                      *
第 1 行出现错误:
ORA-00910: 指定的长度对于数据类型而言过长

SQL> create table o_table5(name nchar(1000));

表已创建。

SQL> create table o_table6(name nvarchar2(2001));
create table o_table6(name nvarchar2(2001))
                                          *
第 1 行出现错误:
ORA-00910: 指定的长度对于数据类型而言过长

SQL> create table o_table6(name nvarchar2(2000));

表已创建。

PostgreSQL:理论最大数据长度是1G,默认值是10 1024 1024=10485760(具体的值由htup_details.h的MaxAttrSize决定)

highgo=# create table p_test3(name char(10485761));
错误:  类型 char 的长度不能超过 10485760
第1行create table p_test3(name char(10485761));
                               ^
highgo=# create table p_test3(name char(10485760));
CREATE TABLE
highgo=# create table p_test4(name varchar(10485761));
错误:  类型 varchar 的长度不能超过 10485760
第1行create table p_test4(name varchar(10485761));
                               ^
highgo=# create table p_test4(name varchar(10485760));
CREATE TABLE

3、定义数据时的参数(字符数)

Oracle:char类型,不带字符数的时候,是1个字符(char(1)),而varchar2必须有字符数。
nchar和nvarchar2分别与char,varchar2类似。

SQL> create table o_test1(name char, addr varchar);
create table o_test1(name char, addr varchar)
                                            *
第 1 行出现错误:
ORA-00906: 缺失左括号

SQL> create table o_test1(name char, addr varchar(5));

表已创建。

SQL> insert into o_test1 values('12','OK');
insert into o_test1 values('12','OK')
                           *
第 1 行出现错误:
ORA-12899: 列 "SCOTT"."O_TEST1"."NAME" 的值太大 (实际值: 2, 最大值: 1)

SQL> insert into o_test1 values('1','OK');

已创建 1 行。

PostgreSQL:char类型,不带字符数的时候,也是默认一个字符(char(1)),而varchar不带字符数的时候,没有限制。

highgo=# create table p_test1(name char, addr varchar);
CREATE TABLE
highgo=# insert into p_test1 values('12', '1234567890');
错误:  对于字符类型来说这个值太长了(1)
highgo=# insert into p_test1 values('1', '1234567890');
INSERT 0 1

4、插入数据库的时候的,字符数超出最大长度部分的处理。

Oracle:报错。即使超出的部分是字符末的空格。

SQL> insert into o_test1 values('1','123456');
insert into o_test1 values('1','123456')
                               *
第 1 行出现错误:
ORA-12899: 列 "SCOTT"."O_TEST1"."ADDR" 的值太大 (实际值: 6, 最大值: 5)

SQL> insert into o_test1 values('1','1234  ');
insert into o_test1 values('1','1234  ')
                               *
第 1 行出现错误:
ORA-12899: 列 "SCOTT"."O_TEST1"."ADDR" 的值太大 (实际值: 6, 最大值: 5)

PostgreSQL:当超出部分是有效的字符的时候,报错。
当是最后的空格时,截断为最大长度,不报错。
但是,当使用明确的类型转换为最大字符数的时候,截断为最大长度,不报错。

highgo=# create table p_test2(name char(2), addr varchar(5));
CREATE TABLE
highgo=# insert into p_test2 values('123', '12345');
错误:  对于字符类型来说这个值太长了(2)
highgo=# insert into p_test2 values('12  ', '12345');
INSERT 0 1
highgo=# insert into p_test2 values(102 :: char(2) , '12345');
INSERT 0 1
highgo=# select * from p_test2;
 name | addr
------+-------
 12   | 12345
 10   | 12345
(2 行记录)

字符类型数据迁移过程中,应该先根据Oracle数据的字符集和数据长度,从类型和长度上保证对方的数据能够完全的转换过来。再注意一些转换过程中SQL的写法,字符型的数据基本上就能够完全的、正确的迁移到PostgreSQL数据库中来了。

参考文档:

PostgreSQL 9.4.4 中文手册:8.3. 字符类型

       http://www.postgres.cn/docs/9.4/datatype-character.html

Database SQL Language Reference:Oracle Built-in Data Types

       http://docs.oracle.com/cd/E11882_01/server.112/e41084/sql_elements001.htm#SQLRF30020
相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍如何基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
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
|
SQL 关系型数据库 数据库
实时计算 Flink版操作报错之使用SQL 将 PostgreSQL 的 date 类型字段转换为 TIMESTAMP 类型时遇到报错,该如何处理
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
|
Oracle NoSQL 关系型数据库
主流数据库对比:MySQL、PostgreSQL、Oracle和Redis的优缺点分析
主流数据库对比:MySQL、PostgreSQL、Oracle和Redis的优缺点分析
2174 3
|
XML JSON 关系型数据库
PostgreSQL支持多种数据类型
PostgreSQL支持多种数据类型
743 2
|
SQL 关系型数据库 MySQL
SQL Server、MySQL、PostgreSQL:主流数据库SQL语法异同比较——深入探讨数据类型、分页查询、表创建与数据插入、函数和索引等关键语法差异,为跨数据库开发提供实用指导
【8月更文挑战第31天】SQL Server、MySQL和PostgreSQL是当今最流行的关系型数据库管理系统,均使用SQL作为查询语言,但在语法和功能实现上存在差异。本文将比较它们在数据类型、分页查询、创建和插入数据以及函数和索引等方面的异同,帮助开发者更好地理解和使用这些数据库。尽管它们共用SQL语言,但每个系统都有独特的语法规则,了解这些差异有助于提升开发效率和项目成功率。
1399 0
|
人工智能 Oracle 关系型数据库
一篇文章弄懂Oracle和PostgreSQL的Database Link
一篇文章弄懂Oracle和PostgreSQL的Database Link
|
分布式计算 DataWorks 关系型数据库
DataWorks产品使用合集之在使用 DataWorks 数据集成同步 PostgreSQL 数据库中的 Geometry 类型数据如何解决
DataWorks作为一站式的数据开发与治理平台,提供了从数据采集、清洗、开发、调度、服务化、质量监控到安全管理的全套解决方案,帮助企业构建高效、规范、安全的大数据处理体系。以下是对DataWorks产品使用合集的概述,涵盖数据处理的各个环节。
200 0
|
分布式计算 关系型数据库 大数据
MaxCompute产品使用合集之怎么才可以将 PostgreSQL 中的 geometry 空间类型字段同步到 MaxCompute 或另一个 PostgreSQL 数据库
MaxCompute作为一款全面的大数据处理平台,广泛应用于各类大数据分析、数据挖掘、BI及机器学习场景。掌握其核心功能、熟练操作流程、遵循最佳实践,可以帮助用户高效、安全地管理和利用海量数据。以下是一个关于MaxCompute产品使用的合集,涵盖了其核心功能、应用场景、操作流程以及最佳实践等内容。
|
SQL Oracle 关系型数据库
|
14天前
|
Oracle 关系型数据库 Linux
【赵渝强老师】Oracle数据库配置助手:DBCA
Oracle数据库配置助手(DBCA)是用于创建和配置Oracle数据库的工具,支持图形界面和静默执行模式。本文介绍了使用DBCA在Linux环境下创建数据库的完整步骤,包括选择数据库操作类型、配置存储与网络选项、设置管理密码等,并提供了界面截图与视频讲解,帮助用户快速掌握数据库创建流程。
188 93

推荐镜像

更多