RODBC 从具有非标准名称的 Access 读取 table
RODBC read table from Access with non-standard name
我正在使用 R 处理 MS Access 中提供的数据集。当我努力使我的代码可重现时,我想避免使用 Access 对数据做任何事情。
数据库中有一些 table 具有非 ascii 字符(波斯语名称)
我连接到数据库:
cns <- odbcConnectAccess2007(mdbfilename)
当我得到 table 的列表时:
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 行 table 的名称包含非标准字符。
在 MS-Access 中显示的 table 的名称是 R80P1 روستایی 80 بخش یک
。因为 MS-Access 尝试在系统的语言环境(波斯语)中发送名称,所以它会将数据转换为 Windows-阿拉伯语编码(代码页 1256),其中不包含波斯语 Yeh (ی
) 的代码(与阿拉伯语 Yeh (ي
) 不同)。
这使得无法从 R 中读取此 table 中的数据,因为我们确实没有名称:
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 中重命名 tables,因为我的脚本将从互联网上下载 30 多个文件,提取它们并阅读它们,这似乎不适合为其中一个文件进行手动重命名文件(有这个奇怪的命名)在过程中。
- 打开连接时更改编码,我已经尝试使用
iconvlist()
提供的所有 374 种编码,但没有解决问题。一个重要的案例:使用 UTF-8
打开 ODBC 连接导致有问题的 table 名称作为 NA
. 返回
- 尝试不按名称而是按数据库中的索引来读取 table,但我不知道如何使用 RODBC 来读取 table(我通过
grepl
ing 初始部分知道索引拉丁文名称)
- 尝试将
sqlFetch()
与自定义 SQL 查询一起使用,该查询在 table 名称上使用正则表达式,我不知道该怎么做,甚至不知道这是否可行。
有什么建议吗?
编辑:
我必须添加我的 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
P.S。对于那些有兴趣解决实际问题的人,我正在谈论的文件可以从以下网址下载:http://www.amar.org.ir/Portals/0/amarmozuii/hazinedaramad/80.rar
(~18 MB)
this is not R's fault, or even MS-Access, as they each do fine with Persian.
这似乎是 RODBC 的限制,它似乎确实依赖 Windows 语言环境来解释 table 名称的字符编码。当我尝试
> 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 语言环境英语(美国)无法识别 任何 Persian/Arabic 字符。此外,即使我直接指定其名称
,我也无法查询table
> 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>]'"
如果您不想重命名源数据库中的 table,那么您可以考虑以下解决方法:
- 创建一个名为“80links.accdb”的新 Access 数据库。
- 使用
External Data > Import & Link > Access
创建一个 linked table 指向源数据库中的 [R80P1 روستاوی 80 بخش یک] table ("80.MDB").
- 重命名链接 table 以使用不带空格的英文名称,例如 [Section_80_rural_R80P1]
- 运行 您对链接 table.
的查询
> 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
我正在使用 R 处理 MS Access 中提供的数据集。当我努力使我的代码可重现时,我想避免使用 Access 对数据做任何事情。
数据库中有一些 table 具有非 ascii 字符(波斯语名称)
我连接到数据库:
cns <- odbcConnectAccess2007(mdbfilename)
当我得到 table 的列表时:
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 行 table 的名称包含非标准字符。
在 MS-Access 中显示的 table 的名称是 R80P1 روستایی 80 بخش یک
。因为 MS-Access 尝试在系统的语言环境(波斯语)中发送名称,所以它会将数据转换为 Windows-阿拉伯语编码(代码页 1256),其中不包含波斯语 Yeh (ی
) 的代码(与阿拉伯语 Yeh (ي
) 不同)。
这使得无法从 R 中读取此 table 中的数据,因为我们确实没有名称:
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 中重命名 tables,因为我的脚本将从互联网上下载 30 多个文件,提取它们并阅读它们,这似乎不适合为其中一个文件进行手动重命名文件(有这个奇怪的命名)在过程中。
- 打开连接时更改编码,我已经尝试使用
iconvlist()
提供的所有 374 种编码,但没有解决问题。一个重要的案例:使用UTF-8
打开 ODBC 连接导致有问题的 table 名称作为NA
. 返回
- 尝试不按名称而是按数据库中的索引来读取 table,但我不知道如何使用 RODBC 来读取 table(我通过
grepl
ing 初始部分知道索引拉丁文名称) - 尝试将
sqlFetch()
与自定义 SQL 查询一起使用,该查询在 table 名称上使用正则表达式,我不知道该怎么做,甚至不知道这是否可行。
有什么建议吗?
编辑:
我必须添加我的 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
P.S。对于那些有兴趣解决实际问题的人,我正在谈论的文件可以从以下网址下载:http://www.amar.org.ir/Portals/0/amarmozuii/hazinedaramad/80.rar (~18 MB)
this is not R's fault, or even MS-Access, as they each do fine with Persian.
这似乎是 RODBC 的限制,它似乎确实依赖 Windows 语言环境来解释 table 名称的字符编码。当我尝试
> 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 语言环境英语(美国)无法识别 任何 Persian/Arabic 字符。此外,即使我直接指定其名称
,我也无法查询table> 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>]'"
如果您不想重命名源数据库中的 table,那么您可以考虑以下解决方法:
- 创建一个名为“80links.accdb”的新 Access 数据库。
- 使用
External Data > Import & Link > Access
创建一个 linked table 指向源数据库中的 [R80P1 روستاوی 80 بخش یک] table ("80.MDB"). - 重命名链接 table 以使用不带空格的英文名称,例如 [Section_80_rural_R80P1]
- 运行 您对链接 table. 的查询
> 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