ORA-29275:部分多字节字符

时间:2009-12-02 05:39:55

标签: sql oracle

我输入的数据来自平面文件,其中包含英文,日文,中文字符。 我将这些值加载到其模式定义为VARCHAR2(250 CHAR)的临时表列中,主表列具有定义VARCHAR2(250)我无法更改。 所以,我在这个专栏上做了一个SUBSTR。在我做了

后加载表格
SELECT * FROM TABLE

...我收到此错误:

  

ORA-29275:部分多字节字符

如果我选择其他列,则没有问题。

3 个答案:

答案 0 :(得分:8)

将数据从SUBSTRB列复制到250 CHAR列时,您应该使用250 byte。此函数仅输出整个字符(您不会获得不完整的unicode字符):

SQL> select substrb('中华人', 1, 9) ch9,
  2         substrb('中华人', 1, 8) ch8,
  3         substrb('中华人', 1, 7) ch7,
  4         substrb('中华人', 1, 6) ch6,
  5         substrb('中华人', 1, 5) ch5
  6    FROM dual;

CH9       CH8      CH7     CH6    CH5
--------- -------- ------- ------ -----
中华人       中华       中华      中华     中

编辑:

@mwardm对结果字符串的实际长度以及结果字符串是否包含无效的字节序列做了一个有趣的评论。请考虑AL32UTF8 DB上的以下内容:

SQL> select lengthb('ÏÏÏ'),
  2         lengthb(substrb('ÏÏÏÏÏÏ', 1, 5)),
  3         dump('ÏÏÏ'),
  4         dump(substrb('ÏÏÏÏÏÏ', 1, 5))
  5    FROM dual;

LE LE DUMP('ÏÏÏ')                           DUMP(SUBSTRB('ÏÏÏÏÏÏ',1,5))
-- -- ------------------------------------- -------------------------------
 6  5 Typ=96 Len=6: 195,143,195,143,195,143 Typ=1 Len=5: 195,143,195,143,32

正如您所看到的,substrb字符串的最后一个字节不是特殊字符的截断的第一个字节,而是编码一个合法字符(此字符集中的前128个字符与ASCII7US字符集相同)所以这对' '空格字符进行编码,使用另一个答案中建议的RTRIM将删除最后一个字符。)

此外,我还使用字符集AL16UTF16得到了这个有趣的结果:

SQL> select lengthb(N'ĈĈ') le,
  2         dump(N'ĈĈ') dump,
  3         lengthb(substrb(N'Ĉ', 1, 3)) length_substr,
  4         dump(substrb(N'ĈĈ', 1, 3)) dump_substr
  5    from dual;

        LE DUMP                    LENGTH_SUBSTR DUMP_SUBSTR
---------- ----------------------- ------------- -----------------
         4 Typ=96 Len=4: 1,8,1,8               2 Typ=1 Len=2: 1,8

在这种情况下,Oracle选择在第二个字节之后剪切字符串,因为在AL16UTF16字符集中没有合法的单字节字符。结果字符串只有2个字节而不是3个字节。

这需要进一步测试,并不是一个严格的演示,但我仍然坚持我的第一个预感substrb将返回编码有效字符串的有效字节序列。

答案 1 :(得分:1)

我想我可能已经找到了一个很好的方法 如果你执行rtrim(substrb('中华人', 1, 8)),则得到'中华',字节长度为预期的6

请尝试

答案 2 :(得分:0)

使用substr将根据数据库字符集的不同而有所不同。我从您的描述中假设您的数据库字符集不是Unicode变体之一,并且您必须将varchar2(250个字符)数据截断为250个BYTES或更少。这很危险,因为它可以在2字节字符的中间停止,从而产生你得到的消息。您应该查看substrc()的文档,它将根据字符计算其长度,而不是字节。

如果您解释为何需要丢弃部分数据,可能会有所帮助。