UTL_FILE и набор символов для испанского - PullRequest
0 голосов
/ 27 марта 2020

Я работал над этим уже несколько дней. Мне нужна помощь в экспорте данных Spani sh из экземпляра БД. Я пытаюсь запросить данные таблицы и экспортировать их в каталог oracle (пример: исходящий), но я вижу, что символы испанского языка sh удаляются. Я использую пакет UTL_FILE для экспорта данных в каталог oracle. Ниже приведен набор символов базы данных:

NLS_CHARACTERSET: US7ASCII NLS_NCHAR_CHARACTERSET: AL16UTF16

Имя таблицы: sp_table1 Имя столбца: 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;
/

Ожидаемый: Servicio de transporte m é dico Фактический: Servicio de transporte medico

1 Ответ

0 голосов
/ 27 марта 2020

Пара предложений.

Во-первых, ваш NLS_CHARACTERSET установлен на US7ASCII, поэтому каждый раз, когда вы используете переменную VARCHAR2 или значение, вы потеряете свои акцентированные символы.

На С другой стороны, ваш NLS_NCHAR_CHARACTERSET установлен на AL16UTF16, поэтому значения NVARCHAR2 должны сохранять ваши акцентированные символы.

Поскольку вы используете DBMS_ SQL, трудно сказать, какие столбцы вы выбираете, но я предполагаю, что один из них - SP_TABLE1.SP_DESCRIPTION, который, как вы говорите, определяется как NVARCHAR2(2000). Однако, похоже, что вы извлекаете это в переменную, определенную как VARCHAR2, поскольку в вашей процедуре нет переменных, определенных как NVARCHAR2. Oracle рад сделать это для вас, выполнив необходимое преобразование, но в процессе вы потеряете своих акцентированных персонажей. Вам нужно будет извлечь этот столбец в переменную, определенную как NVARCHAR2.

Затем, при записи этого значения вам нужно будет использовать процедуру UTL_FILE.PUT_LINE_NCHAR вместо UTL_FILE.PUT_LINE. Первый принимает параметр NVARCHAR2 и должен сохранять ваши акцентированные символы.

...