我在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 بخش ?ک'"
我试着用各种方法解决这个问题
- 在MS-Access中重命名表,因为我的脚本将从互联网下载30多个文件,提取并读取它们,在过程中对其中一个文件(有这种奇怪的命名)进行手动重命名似乎是不可行的
- 打开连接时更改编码,我已经尝试过
iconvlist()
提供的所有374个编码,但并不能解决问题。一个重要的例子是:使用UTF-8
打开ODBC连接,导致有问题的表名返回为NA
- 尝试在数据库中不按名称而是按索引读取表,但我不知道如何使用ROBC(我通过拉丁语中名称的开头部分
grepl
知道索引) - 尝试将
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