1

生の文字列があり、それを varchar2 にキャストしてから生にキャストし直しても、元の情報はすべて残っています。ただし、それを varchar2 にキャストしてから (空の文字列を含む) 何かを連結すると、最後の文字が失われます。これは私がそれを複製するために使用しているコードです:

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 行目の唯一の違いは、v_string が空の文字列と連結された後に 13 行目が実行されることです。しかし、出力は次のとおりです。

Raw string:     C5C6C7
New raw string: C5C6

新しい生の文字列は、何も連結しなければ同じですが、文字列の前に何かを追加すると、最後の部分が失われます。特定のキャラクターでのみ発生します。raw を '61' (小文字の 'a') で終了しても、何も失われません。

Oracle SQL Developer v.3.2.20.09 を使用しています

これはしばらくの間私を混乱させてきました。何かが欠けているのか、それとも単なるバグなのかわかりませんが、助けていただければ幸いです。

4

1 に答える 1

6

とを使用する場合は、使用している文字セット (データベース文字セットとクライアント cs) を提供することが必須ですRAWsVARCHARs

その理由は、すべてのバイト値が から0x00までの raw バイトに対して正当であるため0xFFです。ほとんどの文字セットには不正な値があります。つまり、どの文字にも対応しないバイト値です。

Oracle がそのような値に遭遇した場合、結果は予測不能になる可能性があります。これはおそらくここで起こることです。

たとえば、UTF-8 では、バイナリ表現が「110...」で始まるバイトは、2 バイト文字の最初のバイトです

そして、それはまさにあなたの状況です: a で始まるバイトには、2 バイト文字の最初のバイトのみCで始まるバイナリ表現があります。2 番目のバイトは(8 から B)1100で始まる必要があります。10..したがって、推測する必要がある場合は、多くの不正なバイト値を持つことでよく知られている 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
--------------------------------------------------------------------------------

実際、どの文字セットでも、raw をやみくもに varchar2 にキャストするのは、一般的に悪い考えです。これらの値が有効であることがわかっている場合にのみ、varchar2 にキャストする必要があります(つまり、raw 自体が varchar2 からのキャストです)。

テキスト媒体を介して表示または送信するために、raw を varchar2 で表現する必要がある場合は、hextorawまたはエンコーディング (たとえば)base64を使用する方が安全UTL_ENCODEです。

于 2013-09-03T14:09:46.253 に答える