为什么Oracle为补充unicode字符Chipmunk使用与Java不同的字节长度?


8

我有Java代码将UTF-8字符串修整为我的Oracle(11.2.0.4.0)列的大小,由于Java和Oracle将字符串视为不同的字节长度,最终引发了错误。我已经验证我NLS_CHARACTERSET在Oracle中的参数是“ UTF8”。

我编写了一个使用Unicode花栗鼠表情符号(🐿️)在下面说明我的问题的测试

public void test() throws UnsupportedEncodingException, SQLException {
    String squirrel = "\uD83D\uDC3F\uFE0F";
    int squirrelByteLength = squirrel.getBytes("UTF-8").length; //this is 7
    Connection connection = dataSource.getConnection();

    connection.prepareStatement("drop table temp").execute();

    connection.prepareStatement("create table temp (foo varchar2(" + String.valueOf(squirrelByteLength) + "))").execute();

    PreparedStatement statement = connection.prepareStatement("insert into temp (foo) values (?)");
    statement.setString(1, squirrel);
    statement.executeUpdate();
}

这在测试的最后一行失败,并显示以下消息:

ORA-12899:列
“ MYSCHEMA”。“ TEMP”。“ FOO”的值太大(实际:9,最大值:7)

的设置NLS_LENGTH_SEMANTICSBYTE。不幸的是,我无法更改它,因为它是旧系统。我对增加列的大小不感兴趣,只是可靠地能够预测字符串的Oracle大小。


可悲的是,我在Internet上看到有关此字节数应为多少的相互矛盾的报告。有人说7,有人说8,有人说12(???)。如果将Oracle字段声明为8而不是7,会发生什么情况呢?我意识到,这并没有明确回答您为什么会这样的问题,但可能会为您提供一些答案。
jcolebrand

Answers:


3

接下来是我的猜测。

Java String使用UTF-16编码内部表示的。当getBytes("UTF-8")Java在两种编码之间进行转换时,您可能会使用最新的Java平台。

当您尝试将Java存储String在数据库中时,Oracle还将在Java本机UTF-16和数据库字符集之间进行转换,该字符集由确定NLS_CHARACTERSET

花栗鼠字符于2014年被批准为Unicode标准的一部分(根据您链接的页面),而Oracle 11g rel.2的最新版本于2013年发布

有人可能会认为Oracle使用了不同或过时的字符转换算法,因此服务器上的🐿️字节表示形式(长9个字节)getBytes()与客户端上返回的字节表示形式(7个字节)不同。

我猜想要解决此问题,您可以升级Oracle服务器或将UTF-16用作数据库字符集。


那解决了问题。我的Oracle 11g使用JDK 1.6.0_141而12实例使用JDK 1.8.0_121
agradl

3
请标记问题为已回答,以便下一个人知道此方法是否有效:)
jcolebrand

我讲得太早了,我正在进一步调查以证实我的怀疑-与甲骨文版本无关...敬请
期待

1

问题是与Oracle的处理的补充Unicode字符,当NLS_LENGTH_SEMANTICSUTF8

文档(添加重点)。

UTF8字符集将字符编码为一个,两个或三个字节。它用于基于ASCII的平台。

插入UTF8数据库的补充字符不会损坏数据库中的数据。补充字符被视为占用6个字节的两个独立的用户定义字符。Oracle建议您切换到AL32UTF8,以完全支持数据库字符集中的补充字符。

此外,松鼠字符串中的最后一个代码点是变量选择器,并且是可选的。我使用Unicode字符检查器看到了

将数据库的NLS_CHARACTERSET参数更改为AL32UTF8通过测试后。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.