2013-09-03 1 views
1

Если у меня есть необработанная строка, и я отбрасываю ее в varchar2, а затем отбрасываю обратно в raw, все исходные данные все еще там. Однако, если я передам его в varchar2 и затем конкатенирую с ним что-либо (включая пустую строку), я теряю последний символ. Это код, я использую, чтобы повторить его:Строка теряет последний символ при объединении с пустой строкой в ​​Oracle SQL Developer

SET SERVEROUTPUT ON; 
DECLARE 
    raw_string RAW(100); 
    v_string VARCHAR2(100); 
    raw_string2 RAW(100); 

BEGIN 
    raw_string := 'C5C6C7'; 
    v_string := utl_raw.cast_to_varchar2(raw_string); 

    dbms_output.put_line('Raw string:  ' || utl_raw.cast_to_raw(v_string)); 
    v_string := v_string || ''; 
    dbms_output.put_line('New raw string: ' || utl_raw.cast_to_raw(v_string)); 
END; 
/

Единственное различие между линиями 11 и 13, что линия 13 запускается после v_string объединяется с пустой строкой. Но выход таков:

Raw string:  C5C6C7 
New raw string: C5C6 

Новое сырье строка будет такой же, если я ничего на нем не конкатенации, но если я что-нибудь добавить к строке, даже перед ним, он потеряет эта последняя часть. Это происходит только с определенными символами. Если я закончил с «61» (нижний регистр «a»), то ничего не будет потеряно.

Я использую Oracle SQL Developer v.3.2.20.09

Это было запутанным меня на некоторое время теперь, и я не уверен, если я что-то отсутствует, или если это просто ошибка, но любой помощь будет высоко оценена.

+0

Я запустил ваш скрипт в Toad - Oracle 11g и не получил тот же результат. 'Исходная строка: C5C6C7 Новая необработанная строка: C5C6C7 PL/SQL процедура успешно завершена.' –

ответ

5

Когда вы играете с RAWs и VARCHARs, обязательно, чтобы вы предоставили нам набор символов, который вы используете (набор символов базы данных и клиентские cs).

Причина в том, что каждое значение байта является законным для необработанного байта, от 0x00 до 0xFF. В то время как большинство наборов символов имеют недопустимые значения: байтовые значения, которые не соответствуют символу.

Когда Oracle сталкивается с такими значениями, последствия могут быть непредсказуемыми. Вероятно, это происходит здесь.

Например, в UTF-8, a byte whose binary representation starts with '110...' is the first byte of a two-byte character.

И это как раз ваша ситуация: байт, начинающийся с C, имеет двоичное представление, которое начинается с 1100 и может быть только первым байтом двухбайтового символа. Второй байт должен начинаться с 10.. (с 8 по B). Поэтому, если я должен был догадаться, я бы предсказал, что вы используете UTF-8, который хорошо известен тем, что у него много недопустимых байтовых значений.

Мы можем наблюдать, что использование незаконных UTF-8 значений приводит ко многим проблемам:

SQL> select utl_raw.cast_to_varchar2('C5C6') i0 from dual; 

I0 
-------------------------------------------------------------------------------- 
ÅÆ 

SQL> select utl_raw.cast_to_varchar2('C5C6')||'' i1 from dual; 

I1 
-------------------------------------------------------------------------------- 
Å 

SQL> select utl_raw.cast_to_varchar2('C5C6')||''||'' i2 from dual; 

I2 
-------------------------------------------------------------------------------- 

На самом деле с любым набором символов, это вообще плохая идея, чтобы бросить сырые вслепую в varchar2. Вы только хотите, чтобы бросить на varchar2, когда вы знаете, что эти значения являются законными (то есть raw является литой из varchar2).

Когда вам нужно представить сырым с varchar2, для показа или отправки через текстовую среду, безопаснее использовать либо hextoraw или кодировку (например base64 с UTL_ENCODE).

Смежные вопросы