code

가능한 인코딩 목록에서 Oracle VARCHAR2 값을 UTF-8로 변환하려면 어떻게 해야 합니까?

starcafe 2023. 10. 10. 20:46
반응형

가능한 인코딩 목록에서 Oracle VARCHAR2 값을 UTF-8로 변환하려면 어떻게 해야 합니까?

기존의 이유로 Oracle 10 데이터베이스에는 VARCHAR2 열이 있습니다. 여기서 문자 인코딩은 다음과 같이 설정됩니다.AL32UTF8일부 UTF-8이 아닌 값을 포함합니다.값은 항상 다음 문자 집합 중 하나에 있습니다.

  • US-ASCII
  • UTF-8
  • CP1252
  • 라틴어-1

데이터베이스 외부의 깨진 값을 수정하기 위해 Perl 함수를 작성했습니다.이 데이터베이스 열의 값에 대해 이 인코딩 목록을 루프하고 UTF-8로 변환을 시도합니다. 변환에 실패하면 다음 인코딩을 시도합니다.오류 없이 가장 먼저 전환하는 것은 우리가 유지하는 가치입니다.이제 데이터베이스 내부에 이 기능을 복제하여 누구나 사용할 수 있도록 하겠습니다.

그러나 이를 위해 찾을 수 있는 것은 기능뿐인데, 이 기능은 절대 실패하지 않지만 인식하지 못하는 문자에 대한 대체 문자를 삽입합니다.그래서 내가 아는 한 언제 전환이 실패했는지 알 방법이 없습니다.

이를 위해 두 가지 질문이 있습니다.

  1. 문자열을 인코딩 목록 중 하나로 변환하여 성공한 첫 번째 인터페이스를 반환하는 기존 인터페이스가 있습니까?
  2. 그리고 그렇지 않다면 문자열을 인코딩으로 변환할 수 없는 경우 실패를 나타내는 다른 인터페이스가 있습니까?그렇다면 이전 기능을 작성할 수 있습니다.

업데이트:

참고로 이 Postgre를 작성했습니다.PL/pgSQL의 SQL 기능은 내가 필요로 하는 것을 정확하게 수행합니다.

CREATE OR REPLACE FUNCTION encoding_utf8(
    bytea
) RETURNS TEXT LANGUAGE PLPGSQL STRICT IMMUTABLE AS $$
DECLARE
    encoding TEXT;
BEGIN
    FOREACH encoding IN ARRAY ARRAY[
        'UTF8',
        'WIN1252',
        'LATIN1'
    ] LOOP
        BEGIN
            RETURN convert_from($1, encoding);
        EXCEPTION WHEN character_not_in_repertoire OR untranslatable_character THEN
            CONTINUE;
        END;
    END LOOP;
END;
$$;

오라클에서 이와 동등한 작업을 수행하는 방법을 알고 싶습니다.

@collapsar의 UTF-8의 불법 캐릭터에 대한 주요 정보와 동료가 파헤친 정보 덕분에 다음과 같이 생각해 냈습니다.

CREATE OR REPLACE FUNCTION reencode(string IN VARCHAR2) RETURN VARCHAR2
AS
    encoded VARCHAR2(32767);
    type  array_t IS varray(3) OF VARCHAR2(15);
    array array_t := array_t('AL32UTF8', 'WE8MSWIN1252', 'WE8ISO8859P1');
BEGIN
    FOR I IN 1..array.count LOOP
        encoded := CASE array(i)
            WHEN 'AL32UTF8' THEN string
            ELSE CONVERT(string, 'AL32UTF8', array(i))
        END;
        IF instr(
            rawtohex(
                utl_raw.cast_to_raw(
                    utl_i18n.raw_to_char(utl_raw.cast_to_raw(encoded), 'utf8')
                )
            ),
            'EFBFBD'
        ) = 0 THEN
            RETURN encoded;
        END IF;
    END LOOP;
    RAISE VALUE_ERROR;
END;

신기하게도 WE8까지는.ISO8859P1: WE8MSWIN1252는 제가 가지고 있는 800여개의 나쁜 값들의 목록들을 불만없이 전부 변환합니다.Perl 또는 Postgre의 경우에도 동일하지 않습니다.SQL 구현: 일부 값의 경우 CP1252는 실패하지만 ISO-8859-1은 성공합니다.그래도 오라클에서 나온 값이 적절한 것 같고 유효한 유니코드인 것 같습니다(Postgre에 로드하여 테스트함).SQL), 그래서 불평할 수 없습니다.이 정도면 제 데이터를 소독할 수 있을 것 같습니다.

데이터베이스 열에 잘못된 utf-8이 포함되어 있는지 확인하려면 다음 쿼리를 사용합니다.

 select CASE
            INSTR (
                  RAWTOHEX (
                      utl_raw.cast_to_raw (
                          utl_i18n.raw_to_char (
                                utl_raw.cast_to_raw ( <your_column> )
                              , 'utf8'
                          )
                      )
                  )
                , 'EFBFBD'
            )
        WHEN 0 THEN 'OK'
        ELSE 'FAIL' 
        END
   from <your_table>
      ;

당신의 db charset이 al32utf8임을 감안하면.

라는 점에 주목합니다.EF BF BDutf-8에서 잘못된 인코딩을 나타냅니다.

표시한 다른 모든 문자 집합이 바이트 중심이므로 유니코드로의 변환은 실패하지 않지만 다른 코드 포인트를 생성할 수도 있습니다.상황 정보가 없으면 실제 소스 문자 집합을 자동으로 결정할 수 없습니다.

잘부탁드려요, 카스텐

문자 ps: :CP1252->WE8MSWIN1252 LATIN-1->WE8ISO8859P1

언급URL : https://stackoverflow.com/questions/12717363/how-can-i-convert-oracle-varchar2-values-to-utf-8-from-a-list-of-possible-encodi

반응형