r-ROBC-使用非标准名称从Access读取表



我在R中处理MS Access中提供的数据集。当我努力使我的代码可复制时,我想避免使用Access对数据做任何事情。

数据库中有一些表具有非ascii字符(波斯语名称)

我连接到数据库:

cns <- odbcConnectAccess2007(mdbfilename)

当我得到一个表的列表时:

tbls <- sqlTables(cns)
head(tbls ,10) 

我得到这样的东西:

                   TABLE_CAT TABLE_SCHEM                 TABLE_NAME   TABLE_TYPE REMARKS
1  D:\HEIS\DataRAW\80.mdb        <NA>          MSysAccessObjects SYSTEM TABLE    <NA>
2  D:\HEIS\DataRAW\80.mdb        <NA>                   MSysACEs SYSTEM TABLE    <NA>
3  D:\HEIS\DataRAW\80.mdb        <NA> MSysNavPaneGroupCategories SYSTEM TABLE    <NA>
4  D:\HEIS\DataRAW\80.mdb        <NA>          MSysNavPaneGroups SYSTEM TABLE    <NA>
5  D:\HEIS\DataRAW\80.mdb        <NA>  MSysNavPaneGroupToObjects SYSTEM TABLE    <NA>
6  D:\HEIS\DataRAW\80.mdb        <NA>       MSysNavPaneObjectIDs SYSTEM TABLE    <NA>
7  D:\HEIS\DataRAW\80.mdb        <NA>                MSysObjects SYSTEM TABLE    <NA>
8  D:\HEIS\DataRAW\80.mdb        <NA>                MSysQueries SYSTEM TABLE    <NA>
9  D:\HEIS\DataRAW\80.mdb        <NA>          MSysRelationships SYSTEM TABLE    <NA>
10 D:\HEIS\DataRAW\80.mdb        <NA>    R80P1 روستا?? 80 بخش ?ک        TABLE    <NA>

正如您所看到的,第10行中的表名包含非标准字符。MS Access中显示的表的名称为R80P1 روستایی 80 بخش یک。由于MS Access试图以系统的区域设置(波斯语)发送名称,因此它将数据转换为Windows阿拉伯语编码(代码页1256),该编码不包含波斯语Yeh(ی)的代码(与阿拉伯语Yeh(ي)不同)。

这使得无法从R中读取此表中的数据,因为我们实际上没有名称:

tbl <- tbls[10,3]
RD <- sqlQuery(cns,paste0("Select Address from ",tbl))
head(RD)

我得到这个错误:

[1] "07002 17 [Microsoft][ODBC Microsoft Access Driver]COUNT field incorrect "            
[2] "[RODBC] ERROR: Could not SQLExecDirect 'Select Address from R80P1 روستا?? 80 بخش ?ک'"

我试着用各种方法解决这个问题

  1. 在MS-Access中重命名表,因为我的脚本将从互联网下载30多个文件,提取并读取它们,在过程中对其中一个文件(有这种奇怪的命名)进行手动重命名似乎是不可行的
  2. 打开连接时更改编码,我已经尝试过iconvlist()提供的所有374个编码,但并不能解决问题。一个重要的例子是:使用UTF-8打开ODBC连接,导致有问题的表名返回为NA
  3. 尝试在数据库中不按名称而是按索引读取表,但我不知道如何使用ROBC(我通过拉丁语中名称的开头部分grepl知道索引)
  4. 尝试将sqlFetch()与在表名上使用正则表达式的自定义SQL查询一起使用,我不知道如何做到这一点,甚至不知道这是否可能

有什么建议吗?

编辑:我必须添加我的sessionInfo():

R version 3.2.2 (2015-08-14)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 8 x64 (build 9200)
locale:
[1] LC_COLLATE=Persian_Iran.1256  LC_CTYPE=Persian_Iran.1256    LC_MONETARY=Persian_Iran.1256
[4] LC_NUMERIC=C                  LC_TIME=Persian_Iran.1256    
attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     
other attached packages:
[1] data.table_1.9.6 foreign_0.8-65   RODBC_1.3-12     yaml_2.1.13     
loaded via a namespace (and not attached):
[1] tools_3.2.2  chron_2.3-47

附言:对于那些有兴趣解决实际问题的人,我所说的文件可以从以下网站下载:http://www.amar.org.ir/Portals/0/amarmozuii/hazinedaramad/80.rar(~18 MB)

这不是R的错,甚至不是MS Access的错,因为他们每个人都对波斯语做得很好。

这似乎是ROBC的一个限制,它似乎确实依赖于Windows区域设置来解释表名的字符编码。当我尝试时

> tbls <- sqlTables(cns)
> head(tbls, 10)

我得到

                    TABLE_CAT TABLE_SCHEM                 TABLE_NAME
1  C:\__tmp\zzzTest\80.MDB        <NA>          MSysAccessObjects
2  C:\__tmp\zzzTest\80.MDB        <NA>                   MSysACEs
3  C:\__tmp\zzzTest\80.MDB        <NA> MSysNavPaneGroupCategories
4  C:\__tmp\zzzTest\80.MDB        <NA>          MSysNavPaneGroups
5  C:\__tmp\zzzTest\80.MDB        <NA>  MSysNavPaneGroupToObjects
6  C:\__tmp\zzzTest\80.MDB        <NA>       MSysNavPaneObjectIDs
7  C:\__tmp\zzzTest\80.MDB        <NA>                MSysObjects
8  C:\__tmp\zzzTest\80.MDB        <NA>                MSysQueries
9  C:\__tmp\zzzTest\80.MDB        <NA>          MSysRelationships
10 C:\__tmp\zzzTest\80.MDB        <NA>    R80P1 ??????? 80 ??? ??

因为我的Windows区域设置,英语(美国),不识别任何的波斯语/阿拉伯语字符。此外,即使我直接指定的名称,我也无法查询该表

> RD <- sqlQuery(cns, 'SELECT Address FROM [R80P1 روستایی 80 بخش یک]')
> head(RD)
[1] "42S02 -1305 [Microsoft][ODBC Microsoft Access Driver] The Microsoft Access database engine cannot find the input table or query 'R80P1 <U+0631><U+0648><U+0633><U+062A><U+0627><U+06CC><U+06CC> 80 <U+0628><U+062E><U+0634> <U+06CC><U+06A9>'. Make sure it exists and that its name is spelled correctly."
[2] "[RODBC] ERROR: Could not SQLExecDirect 'SELECT Address FROM [R80P1 <U+0631><U+0648><U+0633><U+062A><U+0627><U+06CC><U+06CC> 80 <U+0628><U+062E><U+0634> <U+06CC><U+06A9>]'"                                                                                                                                

如果您不想重命名源数据库中的表,那么您可以考虑以下解决方法:

  • 创建一个名为"80links.accdb"的新Access数据库
  • 使用External Data > Import & Link > Access创建一个链接的表,该表指向源数据库("80.MDB")中的[R80P1
  • 重命名链接表以使用不带空格的英文名称,例如[Section_80_roural_R80P1]
  • 对链接表运行查询
> mdbfilename <- 'C:\__tmp\zzzTest\80links.accdb'
> cns <- odbcConnectAccess2007(mdbfilename)
> RD <- sqlQuery(cns, 'Select Address from Section_80_rural_R80P1')
> head(RD)
  Address
1   11001
2   11001
3   11001
4   11001
5   11001
6   11001

最新更新