Функция dbWriteTable из пакета DBI изменяет кодировку символов

#r #oracle #encoding #dbi #roracle

Вопрос:

Я столкнулся с проблемой при использовании функции dbWriteTable из пакета DBI (также входящей в пакет ROracle).

Я пытаюсь экспортировать data.frame на сервер Oracle, где data.frame содержит столбец со смешанной кодировкой («неизвестно» и «UTF-8»). Если я экспортирую все строки на сервер Oracle, то символы с акцентом (таким образом, символы UTF-8) становятся символами, отличными от UTF-8 на сервере Oracle, в то время как если я экспортирую только те строки, которые имеют кодировку UTF-8, то символы отображаются правильно на Oracle.

Мне кажется, что функция dbWriteTable понижает кодировку до самого низкого уровня, найденного в столбце. Это ошибка в функции dbWriteTable или я неправильно настроил кодировку? Кто-нибудь знает способ решения этой проблемы?

Код, с помощью которого вы могли бы воспроизвести проблему, с которой я столкнулся:

 # Library
library("ROracle")

# Parameters
oracle_username   <- "USER"
oracle_password   <- "PASSWORD"
oracle_table_name <- "PLEASE_GIVE_A_NAME"

# Oracle kapcsolat
connection_string <- "THIS_IS_COMPANY_SPECIFIC"
drv               <- DBI::dbDriver("Oracle")

# Setting up the connection
con <- DBI::dbConnect(drv, username = oracle_username, password = oracle_password, dbname = connection_string) 

# Table to be exported to Oracle
dt_example <- as.data.frame(STRING = c("Unknown Urszula", "UTF-8 Uránia"))

# Checking the encoding
Encoding(dt_example$STRING)

# Exporting all rows
DBI::dbExecute(con, paste("drop table", toupper(oracle_table_name)))
DBI::dbWriteTable(con, name = toupper(oracle_table_name), value = dt_example, overwrite = TRUE, append = FALSE)
# --> The result on the server is Unknown Urszula and UTF-8 Ur??nia

# Exporting only the row with UTF-8 encoding
DBI::dbExecute(con, paste("drop table", toupper(oracle_table_name)))
DBI::dbWriteTable(con, name = toupper(oracle_table_name), value = dt_example[2, ], overwrite = TRUE, append = FALSE)
# --> The result on the server is UTF-8 Uránia
 

У меня есть следующая система / среда:

 > R.version
               _                           
platform       x86_64-suse-linux-gnu       
arch           x86_64                      
os             linux-gnu                   
system         x86_64, linux-gnu           
status                                     
major          3                           
minor          5.0                         
year           2018                        
month          04                          
day            23                          
svn rev        74626                       
language       R                           
version.string R version 3.5.0 (2018-04-23)
 
 > Sys.getlocale()
[1] "LC_CTYPE=en_US.UTF-8;LC_NUMERIC=C;LC_TIME=en_US.UTF-8;LC_COLLATE=en_US.UTF-8;LC_MONETARY=en_US.UTF-8;LC_MESSAGES=en_US.UTF-8;LC_PAPER=en_US.UTF-8;LC_NAME=C;LC_ADDRESS=C;LC_TELEPHONE=C;LC_MEASUREMENT=en_US.UTF-8;LC_IDENTIFICATION=C"
 
 > Sys.getenv(c("LANG", "ORACLE_HOME"))
                               LANG                         ORACLE_HOME 
                      "en_US.UTF-8" "/usr/lib/oracle/12.1/client64/lib" 
 

Параметр NLS_LANG имеет значение AMERICAN_AMERICA.EE8ISO8859P2 в операционной системе.

Сервер Oracle имеет следующую настройку NLS:

 select * from V$NLS_PARAMETERS;

NLS_LANGUAGE    AMERICAN
NLS_TERRITORY   AMERICA
NLS_CURRENCY    $
NLS_ISO_CURRENCY    AMERICA
NLS_NUMERIC_CHARACTERS  .,
NLS_CALENDAR    GREGORIAN
NLS_DATE_FORMAT DD-MON-RR
NLS_DATE_LANGUAGE   AMERICAN
NLS_CHARACTERSET    EE8ISO8859P2
NLS_SORT    BINARY
NLS_TIME_FORMAT HH.MI.SSXFF AM
NLS_TIMESTAMP_FORMAT    DD-MON-RR HH.MI.SSXFF AM
NLS_TIME_TZ_FORMAT  HH.MI.SSXFF AM TZR
NLS_TIMESTAMP_TZ_FORMAT DD-MON-RR HH.MI.SSXFF AM TZR
NLS_DUAL_CURRENCY   $
NLS_NCHAR_CHARACTERSET  AL16UTF16
NLS_COMP    BINARY
NLS_LENGTH_SEMANTICS    BYTE
NLS_NCHAR_CONV_EXCP FALSE
 

Любая помощь будет признательна! Заранее благодарю вас!

Комментарии:

1. При работе с символами UTF-8 я бы установил значение NLS_LANG AMERICAN_AMERICA.AL32UTF8 .

2. Спасибо вам за предложение! Честно говоря, у меня есть сомнения, что это решит проблему, потому что, если я экспортирую строки, содержащие хотя бы один символ UTF-8 в каждой строке, — например as.data.frame(STRING = c("UTF-8 Uránia")) , — результаты в Oracle будут в порядке. Это наводит меня на мысль, что Oracle может правильно распознавать символы UTF-8.