ORA-29275: частичный многобайтовый символ - PullRequest
2 голосов
/ 02 декабря 2009

У меня есть входные данные, поступающие из плоского файла с английскими, японскими, китайскими иероглифами в одном столбце. Я загружаю эти значения в столбец промежуточной таблицы, чье определение схемы VARCHAR2 (250 CHAR), столбец основной таблицы имеет определение VARCHAR2 (250), которое я не могу изменить. Итак, я делаю SUBSTR в этой колонке. После загрузки таблицы, когда я сделал

SELECT * FROM TABLE

... Я получаю эту ошибку:

ORA-29275: частичный многобайтовый символ

Если я выберу другие столбцы, проблем не будет.

Ответы [ 3 ]

8 голосов
/ 02 декабря 2009

вы должны использовать SUBSTRB, когда копируете данные из столбца 250 CHAR в столбец 250 byte. Эта функция будет выводить только целые символы (вы не получите неполные символы Юникода):

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
--------- -------- ------- ------ -----
中华人       中华       中华      中华     中

Edit:

@ mwardm сделал интересный комментарий относительно фактической длины полученной строки и того, может ли полученная строка содержать недопустимую последовательность байтов. Рассмотрим следующее на БД AL32UTF8:

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 голос
/ 18 июля 2012

Я думаю, я мог бы найти хороший способ сделать это если вы сделаете rtrim(substrb('中华人', 1, 8)), вы получите '中华' и ожидаемую длину в байтах 6

пожалуйста, попробуйте

0 голосов
/ 02 декабря 2009

Использование substr будет вести себя по-разному в зависимости от набора символов базы данных. Из вашего описания я предполагаю, что ваш набор символов БД не является одним из вариантов Unicode, и вы должны усечь данные varchar2 (250 символов) до 250 БАЙТОВ или меньше. Это опасно, потому что может остановиться в середине двухбайтового символа, что приведет к полученному вами сообщению. Вы должны посмотреть документацию для substrc (), которая вычислит его длину на основе символов, а не байтов.

Это может помочь, если вы объясните больше, почему вы должны выбросить часть данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...