当我尝试将 R 与 Access 数据库连接时,出现错误
odbcConnectAccess is only usable with 32-bit Windows
有谁知道如何解决这个问题?
library(RODBC)
mdbConnect<-odbcConnectAccess("D:/SampleDB1/sampleDB1.mdb")
改为使用odbcDriverConnect
。如果您安装了 64 位 R,则可能必须使用 32 位 R 版本。
odbcDriverConnect("Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=D:/SampleDB1/sampleDB1.mdb")
这是一个函数,它将数据从 32 位访问传输到 64 位 R,而无需保存任何文件。该函数构建一个表达式字符串,该字符串传递给第二个 32 位会话;然后使用套接字服务器包(svSocket)将数据返回到原始会话。需要注意的一点是,socket 服务器将访问数据保存在全局环境中,所以第二个参数用于定义输出,而不是使用“<-”来保存输出。
access_query_32 <- function(db_table = "qryData_RM", table_out = "data_access") {
library(svSocket)
# variables to make values uniform
sock_port <- 8642L
sock_con <- "sv_con"
ODBC_con <- "a32_con"
db_path <- "~/path/to/access.accdb"
if (file.exists(db_path)) {
# build ODBC string
ODBC_str <- local({
s <- list()
s$path <- paste0("DBQ=", gsub("(/|\\\\)+", "/", path.expand(db_path)))
s$driver <- "Driver={Microsoft Access Driver (*.mdb, *.accdb)}"
s$threads <- "Threads=4"
s$buffer <- "MaxBufferSize=4096"
s$timeout <- "PageTimeout=5"
paste(s, collapse=";")
})
# start socket server to transfer data to 32 bit session
startSocketServer(port=sock_port, server.name="access_query_32", local=TRUE)
# build expression to pass to 32 bit R session
expr <- "library(svSocket)"
expr <- c(expr, "library(RODBC)")
expr <- c(expr, sprintf("%s <- odbcDriverConnect('%s')", ODBC_con, ODBC_str))
expr <- c(expr, sprintf("if('%1$s' %%in%% sqlTables(%2$s)$TABLE_NAME) {%1$s <- sqlFetch(%2$s, '%1$s')} else {%1$s <- 'table %1$s not found'}", db_table, ODBC_con))
expr <- c(expr, sprintf("%s <- socketConnection(port=%i)", sock_con, sock_port))
expr <- c(expr, sprintf("evalServer(%s, %s, %s)", sock_con, table_out, db_table))
expr <- c(expr, "odbcCloseAll()")
expr <- c(expr, sprintf("close(%s)", sock_con))
expr <- paste(expr, collapse=";")
# launch 32 bit R session and run expressions
prog <- file.path(R.home(), "bin", "i386", "Rscript.exe")
system2(prog, args=c("-e", shQuote(expr)), stdout=NULL, wait=TRUE, invisible=TRUE)
# stop socket server
stopSocketServer(port=sock_port)
# display table fields
message("retrieved: ", table_out, " - ", paste(colnames(get(table_out)), collapse=", "))
} else {
warning("database not found: ", db_path)
}
}
有时,此函数会返回错误,但它不会影响数据检索,并且似乎是关闭套接字服务器连接的结果。
可能还有改进的余地,但这提供了一种简单快捷的方法,可以将数据从 32 位访问中提取到 R 中。
给出的答案没有成功,但这是最终为我成功的一步一步的方法。在 64 位上安装 Windows 8。安装了 64 位和 32 位 R。我的访问是 32 位的。
现在我可以运行我喜欢的代码了
channel <- odbcConnect("ProjectnameAcc")
Table1Dat <- sqlFetch(channel, "Table1")
我在遇到类似问题时遇到了这个 SO,此时我们至少还有一个使用极其灵活的 odbc 库的选项。
不过这里有一个重要说明:MS Access ODBC 驱动程序不是默认 MS Office 安装的一部分,因此您必须从 Microsoft 下载适当的驱动程序(在我的情况下为 Microsoft Access Database Engine 2016 Redistributable)并确保下载适当的位数(例如 AccessDatabaseEngine_X64.exe)。下载后,它应该会自动显示在您的 Windows ODBC 数据源(64 位)实用程序中,或者您可以在 R 会话中使用 odbcListDrivers 函数进行确认。
library(odbc)
# run if you want to see what drivers odbc has available
# odbcListDrivers()
# full file path to Access DB
file_path <- "~/some_access_file.accdb"
# pass MS Access file path to connection string
accdb_con <- dbConnect(drv = odbc(), .connection_string = paste0("Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=",file_path,";"))
使用其他人的建议,这是一个将 32 位 Access 数据转换为 64 位 R 的显式示例,您可以将其写入脚本,这样您就不需要手动执行这些步骤。您确实需要在您的机器上安装 32 位 R 才能运行此脚本,并且此脚本假定 32 位 R 的默认位置,因此请根据需要进行调整。
第一个代码部分进入您的主脚本,第二个代码部分是您创建并从主脚本调用的一个小 R 脚本文件的全部内容,这种组合提取并保存然后从 access 数据库加载数据,而无需不得不停下来。
这是我的主脚本中的部分,这是从 64 位 R 中运行的
## Lots of script above here
## set the 32-bit script location
pathIn32BitRScript <- "C:/R_Code/GetAccessDbTables.R"
## run the 32 bit script
system(paste0(Sys.getenv("R_HOME"), "/bin/i386/Rscript.exe ",pathIn32BitRScript))
## Set the path for loading the rda files created from the little script
pathOutUpAccdb <- "C/R_Work/"
## load the tables just created from that script
load(paste0(pathOutUpAccdb,"pots.rda"))
load(paste0(pathOutUpAccdb,"pans.rda"))
## Lots of script below here
这是名为 GetAccessTables.R 的单独脚本
library(RODBC).
## set the database path
inCopyDbPath <- "C:/Projects/MyDatabase.accdb"
## connect to the database
conAccdb <- odbcConnectAccess2007(inCopyDbPath)
## Fetch the tables from the database. Modify the as-is and string settings as desired
pots <- sqlFetch (conAccdb,"tbl_Pots",as.is=FALSE, stringsAsFactors = FALSE)
pans <- sqlFetch(conAccdb,"tbl_Pans",as.is=FALSE, stringsAsFactors = FALSE)
## Save the tables
save(pots, file = "C/R_Work/pots.rda")
save(pans, file = "C:/R_Work/pans.rda")
close(conAccdb)
上面 manotheshark 的函数非常有用,但我想使用 SQL 查询而不是表名来访问数据库,并将数据库名称作为参数传递,因为我通常使用多个 Access 数据库。这是修改后的版本:
access_sql_32 <- function(db_sql = NULL, table_out = NULL, db_path = NULL) {
library(svSocket)
# variables to make values uniform
sock_port <- 8642L
sock_con <- "sv_con"
ODBC_con <- "a32_con"
if (file.exists(db_path)) {
# build ODBC string
ODBC_str <- local({
s <- list()
s$path <- paste0("DBQ=", gsub("(/|\\\\)+", "/", path.expand(db_path)))
s$driver <- "Driver={Microsoft Access Driver (*.mdb, *.accdb)}"
s$threads <- "Threads=4"
s$buffer <- "MaxBufferSize=4096"
s$timeout <- "PageTimeout=5"
paste(s, collapse=";")
})
# start socket server to transfer data to 32 bit session
startSocketServer(port=sock_port, server.name="access_query_32", local=TRUE)
# build expression to pass to 32 bit R session
expr <- "library(svSocket)"
expr <- c(expr, "library(RODBC)")
expr <- c(expr, sprintf("%s <- odbcDriverConnect('%s')", ODBC_con, ODBC_str))
expr <- c(expr, sprintf("%1$s <- sqlQuery(%3$s, \"%2$s\")", table_out, db_sql, ODBC_con))
expr <- c(expr, sprintf("%s <- socketConnection(port=%i)", sock_con, sock_port))
expr <- c(expr, sprintf("evalServer(%s, %s, %s)", sock_con, table_out, table_out))
expr <- c(expr, "odbcCloseAll()")
expr <- c(expr, sprintf("close(%s)", sock_con))
expr <- paste(expr, collapse=";")
# launch 32 bit R session and run the expression we built
prog <- file.path(R.home(), "bin", "i386", "Rscript.exe")
system2(prog, args=c("-e", shQuote(expr)), stdout=NULL, wait=TRUE, invisible=TRUE)
# stop socket server
stopSocketServer(port=sock_port)
# display table fields
message("Retrieved: ", table_out, " - ", paste(colnames(get(table_out)), collapse=", "))
} else {
warning("database not found: ", db_path)
}
}
我在弄清楚如何调用 manotheshark 的函数时也遇到了一些困难,并且需要深入研究 svSocket 包文档才能意识到调用脚本需要实例化将返回数据的对象,然后传递其名称(而不是对象本身)在 table_out 参数中。这是一个调用我修改后的版本的 R 脚本示例:
source("scripts/access_sql_32.R")
spnames <- data.frame()
# NB. use single quotes for any embedded strings in the SQL
sql <- "SELECT name as species FROM checklist
WHERE rank = 'species' ORDER BY name"
access_sql_32(sql, "spnames", "X:/path/path/mydata.accdb")
这可行,但有局限性。
首先,避免任何 Microsoft Access SQL 扩展。例如,如果您使用 Access Query 构建器,它通常会插入字段名称,例如[TABLE_NAME]![FIELD_NAME]
. 这些都行不通。Access 还允许以“10kmSq”等数字开头的非标准字段名称,并允许您在 SQL 中使用它们,例如SELECT [10kmSq] FROM ...
. 这也行不通。如果 SQL 语法有错误,返回变量将包含错误消息。
其次,您可以返回的数据量似乎仅限于 64Kb。如果您尝试运行返回过多的 SQL,则 32 位会话不会终止并且脚本会挂起。
以下解决方案对我有用:在read-data-from-32-bit-access-db-using-64-bit-R上找到它说 要从以下位置安装 64 位数据库引擎:microsoft`
然后:找到并运行“ODBC-datasources (64-bits)”。
然后在R中:
library(RODBC)
dcon <- dbConnect(odbc::odbc(), "name-you-gave-to-your-datasource-in-3")
我正在运行 Windows 10 x64、Office 365 x64(不确定是否相关)和 R 64 位。我不需要切换到 32 位 R。
就我而言,我通过安装 64 位版本的Microsoft Access Database Engine 2016 Redistributable然后提供我自己的帐户(rsession.exe 运行为)对注册表项具有完全控制权限来使其工作。HKEY_LOCAL_MACHINE\SOFTWARE\ODBC
注册表项的权限没有意义。我的帐户已经是此 PC管理员组的成员,并且该组已经对该密钥具有完全控制权限。
我使用的命令:
library("odbc")
accdb_con <- dbConnect(drv = odbc(), .connection_string = paste0("Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=C:/full_path_to_file/buildings.mdb;"))