Postgresql(Oracle兼容) 到Oracle19.9字符语义

Oracle与PostgreSQL使用差异对比与总结 JDBC连接: Oracle的jdbc连接字符串:db.url=jdbc:oracle:thin:@192.168.1.1:1521:ORCL Postgresql的连接字符串:db.url=jdbc:postgresql:@192.168.1.1:5432/database 1、基本数据类型差异 Oracle PostgreSQL Varchar2 varchar n... 阅读详情

一、测试背景

1.1 目的

Postgresql(Oracle兼容)与 Oracle 数据库在处理字符类型字段(VARCHAR / VARCHAR2)时,长度语义(字符 vs 字节) 的差异,以及客户端字符集环境(NLS_LANG)对 Oracle 插入操作的影响。

1.2 测试环境

项目

源端(postgresql)

目标端(Oracle)

数据库版本

Postgresql(Oracle兼容)

Oracle 19c Standard Edition 2 (19.9.0.0.0)

字符集

UTF-8

AL32UTF8

默认长度语义

nls_length_semantics = char

(按字符)

nls_length_semantics = byte

(按字节,默认)

测试客户端

psql

SQL*Plus / DBeaver

1.3 测试数据

  • 中文字符串:'中华人民共和国'(共 7 个字符)

  • UTF-8 编码字节数:21 字节(每个汉字 3 字节)


二、测试步骤与原始现象

2.1 Postgresql(源端)测试

sql

-- 建表(不显式指定单位,依赖默认语义)CREATE TABLE test_highgo_utf8 (a VARCHAR(10));
-- 插入数据INSERT INTO test_highgo_utf8 (a) VALUES ('中华人民共和国');
-- 查询存储结果SELECT a, LENGTHB(a) AS bytes_length, LENGTH(a) AS char_length FROM test_highgo_utf8;

结果:

结论:postgresql默认 VARCHAR(10) 存储 10 个字符(而非 10 字节),因此 7 个汉字可正常存储。


2.2 Oracle 数据库(目标端)测试

场景 A:通过 SQL*Plus 插入(未设置 NLS_LANG)

sql

-- 建表(显式指定 CHAR 语义)CREATE TABLE test_oracle_utf8 (a VARCHAR2(10 CHAR));
-- 插入相同数据INSERT INTO test_oracle_utf8 (a) VALUES ('中华人民共和国');

结果:

查询表定义:

SELECT column_name, char_used, char_length, data_lengthFROM user_tab_columns WHERE table_name = 'TEST_ORACLE_UTF8';

Plain Text

输出:CHAR_USED = 'C', CHAR_LENGTH = 10, DATA_LENGTH = 40 —— 表明列定义正确为字符语义。初步困惑:为什么显式 CHAR 语义仍报字节超限?

场景 B:通过 DBeaver(JDBC 驱动)插入

同样使用 VARCHAR2(10 CHAR) 表,通过 DBeaver 执行:

sql

INSERT INTO test_oracle_utf8 (a) VALUES ('中华人民共和国');

Plain Text

关键发现:相同的表、相同的 SQL,在不同客户端下结果不同 → 问题不在数据库,而在客户端环境。


三、根本原因分析

3.1 Oracle 字符集转换机制

Oracle 的 NLS_LANG 环境变量决定了客户端(SQL*Plus)如何将输入字符转换为数据库字符集。其格式为:

当客户端输入字符串时:

  1. SQL*Plus 认为输入字符的编码为 NLS_LANG 中指定的字符集。

  2. SQL*Plus 将输入字符串从该字符集转换为数据库字符集(NLS_CHARACTERSET)。

  3. 数据库按转换后的字节序列存储。

3.2 本次错误的详细拆解

环境状态

数据库字符集:AL32UTF8(汉字 → 3 字节)

错误过程

  1. 用户在 SQL*Plus 中输入 '中华人民共和国'(终端通常为 UTF-8 编码,每个汉字 3 字节,共 21 字节)。

  2. 数据库最终收到的数据字节数大于 21 字节(本例中报错 actual:21 恰好是原始 UTF-8 长度,说明转换后字节数未变但语义错误;某些情况下字节数会更大)。

结论

问题不是 Oracle 的 CHAR 语义失效,而是客户端 NLS_LANG 配置错误,导致 SQL*Plus 在字符集转换过程中产生异常,最终使数据库认为数据长度超限。

3.3 DBeaver 为何成功?

DBeaver 使用 JDBC 驱动(oracle.jdbc.OracleDriver),驱动内部会正确处理字符集转换,无需依赖 NLS_LANG 环境变量。它通过 JDBC URL 参数(如 useUnicode=true&characterEncoding=UTF-8)或自动检测数据库字符集来完成转换,因此不受此问题影响。

四、测试结论

  1. Oracle 19c 中 VARCHAR2(10 CHAR) 语义完全正常在正确的客户端字符集配置下,可以成功存储 7 个汉字(21 字节),因为 CHAR 语义限制的是字符个数,而非字节数。

  2. postgresql数据库默认按字符存储,与 Oracle 显式 CHAR 语义行为一致测试中postgresql VARCHAR(10) 同样成功存储 7 个汉字,两者在正确配置下可兼容。

  3. ORA-12899 错误的直接原因是客户端 NLS_LANG 未正确设置SQL*Plus 依赖此变量进行字符集转换,错误配置会导致传输字节数异常,触发长度超限。

  4. 图形化工具(DBeaver、Navicat 等)及 JDBC 驱动不受此问题影响它们内置字符集处理逻辑,无需手工配置 NLS_LANG。

补充(Xshell终端编码 → CentOS系统locale → Oracle NLS_LANG → 数据库字符集)

五、数据同步建议(针对异构同步)

在将数据从postgresql同步到 Oracle 时,为避免字符长度相关错误,请遵循以下清单:

检查项

操作

源端字段分析

计算源端字段的实际最大字节数:

SELECT MAX(LENGTHB(column)) FROM table;

目标端字段设计

使用 VARCHAR2(N CHAR),其中 N ≥ 源端最大字符数。若不确定,可预留 4 倍

同步工具环境

如果同步任务通过 SQL*Plus 执行,

必须正确设置 NLS_LANG

Oracle 19c通过DBLink连接PostgreSQL 14保姆级教程(含ODBC驱动避坑指南) 本文提供Oracle 19c通过DBLink连接PostgreSQL 14的详细教程,涵盖从环境准备、ODBC驱动编译、透明网关配置到创建DBLink的全过程。重点解析了ODBC驱动编译中的常见错误、字符集配置等关键避坑点,并给出了生产环境下的稳定性优化建议与故障排查指南,助力企业实现异构数据库的高效、稳定互联。 阅读详情

相关推荐

Oracle到PostgreSQL迁移:使用orafce工具处理Oracle函数

orafce是一个开源的函数包,它提供了Oracle数据库中常用函数和包的PostgreSQL实现,以便在PostgreSQL中模拟Oracle的行为。orafce中的函数覆盖了包括日期时间、字符串处理、数值计算等多种类别,这些函数对于在PostgreSQL中迁移和运行Oracle兼容的应用程序至关重要。Oracle数据库支持众多数据类型,这些类型包括数值型、字符型、日期时间型等,它们在设计数据库表结构和处理数据时起到核心作用。

weixin_42514750的博客 1496

PostgreSQL ''空字符处理(兼容oracle)

PostgreSQL中的’‘空字符是属于字符串类型的数据,而在oracle中,’'会默认转换成NULL,所以可以使用任何数据类型。 例子: oracle: 建表: varchar和date类型都支持’'空字符。 SQL> create table t1(id int, c1 varchar2(10) default '', c2 date default ''); Table creat...

Focus on PostgreSQL 3829

keil自动分配SDRAM空间设置使用

1.修改.sct文件。

qizhi321123的博客 1404

PostgreSQL字符串内嵌空字符解决方法(兼容oracle chr(0))

今天在群里看到有人问:oracle迁移pg \0问题如何解决?查了下资料: 在Oracle中存储数据时,先是存储这一列的长度,然后存储列数据本身。而对于NULL,只包含一个FF,没有数据部分。简单的说,Oracle用长度FF来表示NULL。 在oracle中是允许在字符串中插入空字符的。 不过需要注意的是: ORACLE里面的空字符串’’和C里面的空字符串””不同。C里面的空字符串并非不不含任何数...

Focus on PostgreSQL 3638

408王道考研【数据结构】思维导图(章节详细可下载xmind文件)

由于图片太多,不一一放上来了,还有部分章节【查找、排序、B树B+树等】在百度网盘,可以关注我的公众号领取【完整的图片+xmind文件】,如想要获取xmind文件的同学可以关注我的个人公众号“小柒很爱喵”,回复“数据结构导图”,可获得以上导图原图和xmind文件(可修改导图内容、查看导图隐藏的笔记与备注,即上图带杠杠的地方是我进一步助于理解的解释)。 希望对你们...

weixin_41950078的博客 7984

JW01二氧化碳传感器实战:5分钟搞定Arduino环境监测系统(附完整代码)

本文详细介绍了如何使用JW01二氧化碳传感器与Arduino快速搭建环境监测系统。通过简单的硬件连接和完整的代码示例,读者可以在5分钟内实现CO2浓度实时监测,并了解数据解析、常见问题解决及进阶应用扩展。JW01传感器的高精度和易用性使其成为创客和嵌入式开发者的理想选择。

kite3的博客 382

PostgreSQL实现字符串运算的隐式转换(兼容oracle)

在oracle中,我们如果对两个字符串类型的数字进行加减之类的运算,oracle可以自动将其转换成数值然后进行运算。 例如: SQL> select '2' - '1' from dual; '2'-'1' ---------- 1 但是在pg中是不会自动进行转换的,我们查看数据库中默认的cast,可以发现没有text或者varchar到numeric的转换的。 bill=# \dC Lis

Focus on PostgreSQL 4049

步进电机梯形加减速算法的实现

步进电机梯形加减速算法的实现

m0_69251699的博客 1318

PostgreSQL和Oracle的sql差异

oracle的递归查询中level表示查询深度(或者递归层次),在PG中没有此含义的关键字,需要自行在with recursive实现。PG having语句必须在group by之后,oracle可以在group by之前。null和’’在oracle中是一致的,最终都会存储为null,在PG中会进行区分。Oracle delete语句可以没有from,pg必须要有from。[注:'999999' ---- 6位数为COL1字段的长度]PG中无效的别名,可以尝试加as关键字,例如name。

m0_46478042的博客 1759

中兴交换机配置SSH登录

SSH是在传统的Telnet协议基础上发展起来的一种安全的远程登录协议。发送和接收数据时, SSH会自动对数据进行加密及解密。相比于Telnet,SSH能防止“中间人”攻击、DNS欺骗、IP 欺骗等,无论是在认证方式或者数据传输的安全性上都有很大的提高。SSH用户认证方式有3种,分别为本地(Local)认证、RADIUS认证和TACACS+认证。以表规划数据为例,说明配置SSH登录的步骤。

才怪的博客 7922

Android驱动工程师职位(侧重于Bringup、外设驱动调试、芯片平台经验)

本文摘要:深圳泓京纬科技招聘Android驱动工程师,要求具备Bootloader/LK/Linux Bringup经验,熟悉LPDDR/eMMC/UFS等存储设备调试。文章详细解析了Android系统架构、Linux驱动开发核心概念、设备树作用、串口调试方法等基础知识。重点介绍了存储驱动架构、性能优化和故障排查技巧,包括eMMC识别问题、UFS性能优化、NAND ECC错误处理等实战场景。同时涵盖芯片平台开发经验、跨部门协作调试方法,以及低温环境等特殊场景的问题解决方案。

郑伟强dev的专栏 247

PostgreSQL实现USERENV函数(兼容oracle)

oracle中使用USERENV 函数来获取当前会话变量的函数,支持的参数有: CLINET_INFO 返回最高可达64个字节存储的用户会话信息,可由应用程序使用DBMS_APPLICATION_INFO包。 ENTRYID 返回当前审计条目编号。审计的EntryID序列细粒度的审计记录和定期审计记录之间共享。在分布式SQL语句不能使用这个属性。 ISDBA 如果用户已经被认证...

Focus on PostgreSQL 2403

【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)

输入电压采集上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, 由于二极 管的正向导通特性, 用户反接电源时亦不会烧坏后级电路。图中 R8、R9 组成分压电路, 由单片机 AD 采集 IO 口 P14 采集 AD 值, 并由计算公式电压 =133300(AD/4096)mV;

Naiva的博客 1994

c oracle空字符串,PostgreSQL字符串内嵌空字符解决方法(兼容oracle chr(0))

Oracle在存储数据时,先是存储这一列的长度,然后存储列数据本身。而对于NULL,只包含一个FF,没有数据部分。简单的说,Oracle用长度FF来表示NULL。在oracle中是允许在字符串中插入空字符的。不过需要注意的是:ORACLE里面的空字符串’’和C里面的空字符串””不同。C里面的空字符串并非不不含任何数据,里面还包含了一个字符串结束符/0。C语言中的空字符串””对应Oracle中ASC...

weixin_35038173的博客 739

Python实现商品价格监控与波动分析爬虫项目

本文通过完整的代码示例和详细的技术讲解,展示了如何实现商品价格的自动监控和波动分析。该项目不仅适用于个人购物助手,还可以扩展为商家的竞品监控工具。通过结合数据抓取、存储、分析与可视化,能够帮助我们更好地理解市场趋势并做出优化决策。

2201_76125261的博客 1742

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

codefirst 兼容oracle,PostgreSQL Oracle 兼容性之 - 内核自带的兼容函数

背景PostgreSQL功能上基本可以和Oracle对齐,只是一些语法或者函数名不一样,所以为了做到兼容,有一些兼容包和兼容函数的出现。PostgreSQL自带了一些Oracle兼容函数,如果你觉得不够意思,可以通过orafce插件继续扩展PostgreSQL与Oracle的兼容性(本文不涉及orafce包)。PostgreSQL自带的Oracle兼容函数在源码src/backend/utils/...

weixin_30181187的博客 257

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

oracle q字符,PostgreSQL Oracle 兼容性之 - 字符串 q quote 逃脱符号

背景Oracle,当需要在字符串中包含单引号时,我们需要输入一对单引号。例如SQL> select 'Hello, I''m digoal.' from dual;'HELLO,I''MDIGOAL.------------------Hello, I'm digoal.使用q quote的写法,可以将quote内部的字符串原样输出,避免写多个单引号带来的困惑。q'c text-to-be-...

weixin_39593593的博客 416

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

PostgreSQL与Oracle的差异对比

Postgresql 与 Oracle 相关差异对比 通过查阅资料及实验,以下对比了 Postgresql 9.3 版本与 Oracle 11g版本的相关差异。注意:相关细节仍待考证和完善。 1. 基本语法差异 1.1. 基本数据类型差异 1.2. 基本函数差异 1.2.1. 游标属性 1.2.2. 系统内置函数包 1.3. DDL 差异 ...

m0_37253968的博客 7172

【openGauss】Oracle到postgresql的字符集名称映射表

前言 最近在写支持openGauss的dbms_lob包,其中的converttoblob及converttoclob两个过程涉及到了字符集相关内容(有个参数是nls_charset_id),但openGauss(基于postgresql)中的字符集名称和oracle的不一致,在迁移时,需要进行一些转换,因此本人做了如下整理。 PG-ORACLE字符集映射 以下是PG到Oracle字符集映射表,其中PG字符集清单来自PG官方文档 (http://postgres.cn/docs/13/multibyte.h

DarkAthena的博客 1160

null和空字符串在oracle和postgresql中的不同

null和空字符串在oracle和postgresql中的不同 PostgreSQL的NULL是一个术语,用来代表一个缺失值。而’'是空字符串。举一个可能不太恰当的例子,null就类似于考生没有参加考试,而空值就类似考生参考考试但没有得分。 在postgresql中,空字符串与null是不同的;而在oracle中,空字符串与null相同。 在postgresql中测试: #建表并插入数据 crea...

weixin_42911965的博客 1573

PostgreSQL和Oracle用法上的一些区别

Normal 0 7.8 磅 0 2 false false false EN-US ZH-CN X-NONE

朝着梦想 渐行前进 5946

PostgreSQL Oracle 兼容性 之 TABLE、PIPELINED函数

标签 PostgreSQL , 返回表 , 返回复合类型 , 返回游标 背景 Oracle 通过table, pipelined函数,用于格式化返回类型为table的函数的结果。 Table function concepts There a couple of steps to take when you are working with tabl...

weixin_33720956的博客 1075

PostgreSQL Oracle兼容性之 - '' 空字符

标签 PostgreSQL , Oracle , 兼容性 , ''空字符 , 隐式NULL转换 背景 Oracle 对''有一些特殊的处理,默认会转成NULL。使得''可以适合任意的数据类型。 然而对于PostgreSQL来说,没有做这层转换,所以''并不能输入给任意类型。 Oracle SQL> create table a(id int,...

weixin_34241036的博客 252

mysql、oracle、postgresql兼容适配

mysql、oracle、postgresql区别,怎样兼容适配

m0_73493077的博客 2479

PostgreSQL 内核自带的Oracle兼容函数

标签 PostgreSQL , Oracle , 兼容函数 , Oracle compatible functions 背景 PostgreSQL功能上基本可以和Oracle对齐,只是一些语法或者函数名不一样,所以为了做到兼容,有一些兼容包和兼容函数的出现。 PostgreSQL自带了一些Oracle兼容函数,如果你觉得不够意思,可以通过orafce...

weixin_33943347的博客 771
上一篇: Oracle12c CDB数据库管理表空间
下一篇: Oracle数据库 binary XML data类型同步
initialize1306
博客等级 码龄11年 3粉丝 30原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值