暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

来自utf8的oracle utl_file编码; 缺少字符

askTom 2018-07-03
775

问题描述

我喜欢将大量的文本数据从db导出到文件。
db中的字符集是utf8。
文件中的例外结果是ISO8859P2或mswin1250。

我的数据库设置:

    SELECT * FROM v$nls_parameters;
    1 NLS_LANGUAGE HUNGARIAN 0
    2 NLS_TERRITORY HUNGARY 0
    9 NLS_CHARACTERSET UTF8 0
    10 NLS_SORT HUNGARIAN 0
    16 NLS_NCHAR_CHARACTERSET UTF8 0
    17 NLS_COMP BINARY 0
    18 NLS_LENGTH_SEMANTICS CHAR 0
    19 NLS_NCHAR_CONV_EXCP FALSE 0

    select * from nls_database_parameters;
    1 NLS_RDBMS_VERSION 12.1.0.2.0
    2 NLS_NCHAR_CONV_EXCP FALSE
    15 NLS_NCHAR_CHARACTERSET UTF8
    16 NLS_CHARACTERSET UTF8
    19 NLS_TERRITORY AMERICA
    20 NLS_LANGUAGE AMERICAN

    select * from nls_session_parameters;
    1 NLS_LANGUAGE HUNGARIAN
    2 NLS_TERRITORY HUNGARY
    9 NLS_SORT HUNGARIAN
    15 NLS_COMP BINARY
    16 NLS_LENGTH_SEMANTICS CHAR
    17 NLS_NCHAR_CONV_EXCP FALSE
复制


在服务器目录 (linux) 中创建的文件。我没有更多关于linux字符集设置的信息。

PLSQL代码:

    DECLARE
       v_fh     UTL_FILE.FILE_TYPE;
       v_eol    VARCHAR2(2);
       v_eollen PLS_INTEGER;
       CURSOR cur_sql IS
          
    SELECT T3.ID_RESULT
          ,T3.column1 
    FROM   table1
    WHERE  id_result = 999999
      ;
       "ID_RESULT" DBMS_SQL.NUMBER_TABLE;
       "column1" DBMS_SQL.VARCHAR2A;
    
    BEGIN
       EXECUTE IMMEDIATE 'ALTER SESSION SET NLS_DATE_FORMAT = ''YYYY.MM.DD HH24:MI:SS''';
       v_eol := CHR(13)||CHR(10);
       v_eollen := LENGTH(v_eol);
       v_fh := UTL_FILE.FOPEN('REP_DIR','result_test.csv','W', 32000);
    
       OPEN cur_sql;
       LOOP
          FETCH cur_sql
          BULK COLLECT INTO "ID_RESULT",
                            "column1",
                            LIMIT 1000;
          IF "ID_RESULT".COUNT > 0 THEN
             FOR i IN "ID_RESULT".FIRST .. "ID_RESULT".LAST LOOP
    
               UTL_FILE.PUT(v_fh, CONVERT("column1"(i),'EE8ISO8859P2','UTF8'));
               UTL_FILE.PUT_nchar(v_fh, v_eol);
    
               UTL_FILE.PUT(v_fh, CONVERT("column1"(i),'EE8MSWIN1250','UTF8'));
               UTL_FILE.PUT(v_fh, v_eol);
    
               UTL_FILE.PUT(v_fh, CONVERT("column1"(i),'EE8ISO8859P2'));
               UTL_FILE.PUT(v_fh, v_eol);
    
               UTL_FILE.PUT(v_fh, CONVERT("column1"(i),'EE8MSWIN1250'));
               UTL_FILE.PUT(v_fh, v_eol);
          
               UTL_FILE.PUT(v_fh, "column1"(i));
               UTL_FILE.PUT(v_fh, v_eol);             
    
               UTL_FILE.PUT(v_fh, utl_raw.cast_to_varchar2(utl_raw.convert(utl_raw.cast_to_raw("column1"(i) ),'HUNGARIAN_HUNGARY.EE8MSWIN1250', 'ENGLISH_UNITED KINGDOM.UTF8')));
               UTL_FILE.PUT(v_fh, v_eol);               
    
               UTL_FILE.fflush(v_fh);
             END LOOP;
          END IF;
          EXIT WHEN cur_sql%NOTFOUND;
       END LOOP;
       CLOSE cur_sql;
       UTL_FILE.FCLOSE(v_fh);
    EXCEPTION
       WHEN 
            .........
          RAISE;
    END;
复制


以db (六进制) 为单位的原始值:
4373 6572 6520 4C61 6A6F 736E E9
Cs er e La jo sn é

记事本中的结果 (在UTF8中编码):

Csere Lajosn

Csere Lajosn

Csere Lajosn

Csere Lajosn

Csere lajoss é

Csere Lajosn

记事本中的结果 (encode in ANSI,char set: windows-1250):

Csere Lajosn

Csere Lajosn

Csere Lajosn

Csere Lajosn

Csere lajoss ă©

Csere Lajosn

记事本中的结果 (在ANSI中编码,char set: iso-8859-2):

Csere Lajosn

Csere Lajosn

Csere Lajosn

Csere Lajosn

Csere lajoss ă š

Csere Lajosn


当我使用CONVERT时,我失去了 “é” 字符。
如何将字符串从UTF8转换为ANSI?

谢谢,
佐尔坦

专家解答



当Oracle支持部门建议时,除特定字符集修复任务外,切勿将CONVERT函数用于任何其他任务。

要以数据库字符集以外的编码生成文件,请以写字节模式 ('wb') 打开文件。然后,使用UTL_I18N.STRING_TO_RAW将您的文本转换为所需的字符集,使其同时为RAW值。然后,使用UTL_FILE.PUT_RAW编写原始值。

我建议定义一个本地过程来进行转换和写入,以简化多个写入请求的编码。
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论