简体   繁体   中英

UTL_FILE and character set for spanish

I have been working on this for days. I need help on Spanish data export from DB instance. I'm trying to query table data and export into oracle Directory (Example:outbound) but I see Spanish accent characters are getting stripped off. I use UTL_FILE package to export data into oracle directory. Below are the database characterset:

NLS_CHARACTERSET :US7ASCII NLS_NCHAR_CHARACTERSET:AL16UTF16

Tablename: sp_table1 Column_name: Sp_description nvarchar2(2000);

    CREATE OR REPLACE PROCEDURE run_query(p_sql IN VARCHAR2
                                     ,p_dir IN VARCHAR2
                                     ,p_file IN VARCHAR2
                     ) IS
  v_finaltxt  VARCHAR2(4000);
  v_v_val     VARCHAR2(4000);
  v_n_val     NUMBER;
  v_d_val     DATE;
  v_ret       NUMBER;
  c           NUMBER;
  d           NUMBER;
  col_cnt     INTEGER;
  f           BOOLEAN;
  rec_tab     DBMS_SQL.DESC_TAB;
  col_num     NUMBER;
  v_fh        UTL_FILE.FILE_TYPE;
  v_delimiter VARCHAR2(1):='|';
BEGIN
  c := DBMS_SQL.OPEN_CURSOR;
  DBMS_SQL.PARSE(c, p_sql, DBMS_SQL.NATIVE);
  d := DBMS_SQL.EXECUTE(c);
  DBMS_SQL.DESCRIBE_COLUMNS(c, col_cnt, rec_tab);
  FOR j in 1..col_cnt
  LOOP
    CASE rec_tab(j).col_type
      WHEN 1 THEN DBMS_SQL.DEFINE_COLUMN(c,j,v_v_val,2000);
      WHEN 2 THEN DBMS_SQL.DEFINE_COLUMN(c,j,v_n_val);
      WHEN 12 THEN DBMS_SQL.DEFINE_COLUMN(c,j,v_d_val);
    ELSE
      DBMS_SQL.DEFINE_COLUMN(c,j,v_v_val,2000);
    END CASE;
  END LOOP;
  -- This part outputs the HEADER
  v_fh := UTL_FILE.FOPEN(upper(p_dir),p_file,'w',32767);
  FOR j in 1..col_cnt
  LOOP
    --v_finaltxt := ltrim(v_finaltxt||','||lower(rec_tab(j).col_name),',');
    v_finaltxt := ltrim(v_finaltxt||v_delimiter||InitCap(rec_tab(j).col_name),v_delimiter); --Pipe
  END LOOP;
  UTL_FILE.PUT_LINE(v_fh, v_finaltxt);
  -- This part outputs the DATA
  LOOP
    v_ret := DBMS_SQL.FETCH_ROWS(c);
    EXIT WHEN v_ret = 0;
    v_finaltxt := NULL;
    FOR j in 1..col_cnt
    LOOP
      CASE rec_tab(j).col_type
        WHEN 1 THEN DBMS_SQL.COLUMN_VALUE(c,j,v_v_val);
                    --v_finaltxt := ltrim(v_finaltxt||',"'||v_v_val||'"',',');
                    v_finaltxt := ltrim(v_finaltxt||v_delimiter||v_v_val||'',v_delimiter);
        WHEN 2 THEN DBMS_SQL.COLUMN_VALUE(c,j,v_n_val);
                    --v_finaltxt := ltrim(v_finaltxt||','||v_n_val,',');
                    v_finaltxt := ltrim(v_finaltxt||v_delimiter||v_n_val,v_delimiter);
        WHEN 12 THEN DBMS_SQL.COLUMN_VALUE(c,j,v_d_val);
                    --v_finaltxt := ltrim(v_finaltxt||','||to_char(v_d_val,'DD/MM/YYYY HH24:MI:SS'),',');
                    v_finaltxt := ltrim(v_finaltxt||v_delimiter||to_char(v_d_val,'YYYYMMDD'),v_delimiter);
      ELSE
        DBMS_SQL.COLUMN_VALUE(c,j,v_v_val);
        --v_finaltxt := ltrim(v_finaltxt||',"'||v_v_val||'"',v_delimiter);
        v_finaltxt := ltrim(v_finaltxt||v_delimiter||v_v_val||'',v_delimiter);
      END CASE;
    END LOOP;
  --  DBMS_OUTPUT.PUT_LINE(v_finaltxt);
    UTL_FILE.PUT_LINE(v_fh, v_finaltxt);
  END LOOP;
  UTL_FILE.FCLOSE(v_fh);
  DBMS_SQL.CLOSE_CURSOR(c);
EXCEPTION
  WHEN UTL_FILE.INVALID_PATH THEN
    UTL_FILE.FCLOSE(v_fh);
    RAISE_APPLICATION_ERROR(-20000, 'File location is invalid.');

  WHEN UTL_FILE.INVALID_MODE THEN
    UTL_FILE.FCLOSE(v_fh);
    RAISE_APPLICATION_ERROR(-20001, 'The open_mode parameter in FOPEN is invalid.');

  WHEN UTL_FILE.INVALID_FILEHANDLE THEN
    UTL_FILE.FCLOSE(v_fh);
    RAISE_APPLICATION_ERROR(-20002, 'File handle is invalid.');

  WHEN UTL_FILE.INVALID_OPERATION THEN
    UTL_FILE.FCLOSE(v_fh);
    RAISE_APPLICATION_ERROR(-20003, 'File could not be opened or operated on as requested.');

  WHEN UTL_FILE.READ_ERROR THEN
    UTL_FILE.FCLOSE(v_fh);
    RAISE_APPLICATION_ERROR(-20004, 'Operating system error occurred during the read operation.');

  WHEN UTL_FILE.WRITE_ERROR THEN
    UTL_FILE.FCLOSE(v_fh);
    RAISE_APPLICATION_ERROR(-20005, 'Operating system error occurred during the write operation.');

  WHEN UTL_FILE.INTERNAL_ERROR THEN
    UTL_FILE.FCLOSE(v_fh);
    RAISE_APPLICATION_ERROR(-20006, 'Unspecified PL/SQL error.');

  WHEN UTL_FILE.CHARSETMISMATCH THEN
    UTL_FILE.FCLOSE(v_fh);
    RAISE_APPLICATION_ERROR(-20007, 'A file is opened using FOPEN_NCHAR, but later I/O ' ||
                                    'operations use nonchar functions such as PUTF or GET_LINE.');

  WHEN UTL_FILE.FILE_OPEN THEN
    UTL_FILE.FCLOSE(v_fh);
    RAISE_APPLICATION_ERROR(-20008, 'The requested operation failed because the file is open.');

  WHEN UTL_FILE.INVALID_MAXLINESIZE THEN
    UTL_FILE.FCLOSE(v_fh);
    RAISE_APPLICATION_ERROR(-20009, 'The MAX_LINESIZE value for FOPEN() is invalid; it should ' || 
                                    'be within the range 1 to 32767.');

  WHEN UTL_FILE.INVALID_FILENAME THEN
    UTL_FILE.FCLOSE(v_fh);
    RAISE_APPLICATION_ERROR(-20010, 'The filename parameter is invalid.');

  WHEN UTL_FILE.ACCESS_DENIED THEN
    UTL_FILE.FCLOSE(v_fh);
    RAISE_APPLICATION_ERROR(-20011, 'Permission to access to the file location is denied.');

  WHEN UTL_FILE.INVALID_OFFSET THEN
    UTL_FILE.FCLOSE(v_fh);
    RAISE_APPLICATION_ERROR(-20012, 'The ABSOLUTE_OFFSET parameter for FSEEK() is invalid; ' ||
                                    'it should be greater than 0 and less than the total ' ||
                                    'number of bytes in the file.');

  WHEN UTL_FILE.DELETE_FAILED THEN
    UTL_FILE.FCLOSE(v_fh);
    RAISE_APPLICATION_ERROR(-20013, 'The requested file delete operation failed.');

  WHEN UTL_FILE.RENAME_FAILED THEN
    UTL_FILE.FCLOSE(v_fh);
    RAISE_APPLICATION_ERROR(-20014, 'The requested file rename operation failed.');

  WHEN OTHERS THEN
    UTL_FILE.FCLOSE(v_fh);
    RAISE;  
END;
/

Expected : Servicio de transporte m é dico Actual: Servicio de transporte medico

A couple of suggestions.

First, your NLS_CHARACTERSET is set to US7ASCII so any time you use a VARCHAR2 variable or value you're going to lose your accented characters.

On the bright side your NLS_NCHAR_CHARACTERSET is set to AL16UTF16, so NVARCHAR2 values should preserve your accented characters.

Because you're using DBMS_SQL it's difficult to tell what columns you're fetching, but I'll guess that one of them is SP_TABLE1.SP_DESCRIPTION which you say is defined as NVARCHAR2(2000) . It appears, however, that you're fetching that into a variable defined as VARCHAR2 since there are no variables defined as NVARCHAR2 in your procedure. Oracle is happy to do this for you, making the necessary conversion, but you're going to lose your accented characters in the process. You're going to need to fetch this column into a variable defined as NVARCHAR2 .

Then, when writing this value out you'll need to use the UTL_FILE.PUT_LINE_NCHAR procedure, rather than UTL_FILE.PUT_LINE . The former takes an NVARCHAR2 parameter, and should preserve your accented characters.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM