53

当我尝试将 R 与 Access 数据库连接时,出现错误

odbcConnectAccess is only usable with 32-bit Windows

有谁知道如何解决这个问题?

library(RODBC) 
mdbConnect<-odbcConnectAccess("D:/SampleDB1/sampleDB1.mdb")
4

8 回答 8

34

改为使用odbcDriverConnect。如果您安装了 64 位 R,则可能必须使用 32 位 R 版本。

odbcDriverConnect("Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=D:/SampleDB1/sampleDB1.mdb")
于 2012-10-25T14:26:46.313 回答
15

这是一个函数,它将数据从 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 中。

于 2016-10-10T15:53:47.300 回答
9

给出的答案没有成功,但这是最终为我成功的一步一步的方法。在 64 位上安装 Windows 8。安装了 64 位和 32 位 R。我的访问是 32 位的。

使用步骤,假设 Windows 8 上的 32 位 Access

  1. 选择 32 位 R(只是 R studio 中的一个设置)
  2. 在 Windows 上搜索设置 ODBC 数据源(32 位)
  3. 转到系统 DSN>添加
  4. 选择 Driver do Microsoft Access (*.mdb) > Finish
  5. 数据源名称:ProjecnameAcc
  6. 描述:项目名称Acc
  7. 确保实际选择数据库> OK

现在我可以运行我喜欢的代码了

channel <- odbcConnect("ProjectnameAcc")
Table1Dat <- sqlFetch(channel, "Table1")
于 2015-10-21T11:47:49.827 回答
6

我在遇到类似问题时遇到了这个 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,";"))
于 2018-08-30T11:55:28.170 回答
2

使用其他人的建议,这是一个将 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)
于 2016-02-11T15:04:34.017 回答
2

上面 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 位会话不会终止并且脚本会挂起。

于 2017-10-25T11:49:05.027 回答
2

以下解决方案对我有用:在read-data-from-32-bit-access-db-using-64-bit-R上找到它说 要从以下位置安装 64 位数据库引擎:microsoft`

然后:找到并运行“ODBC-datasources (64-bits)”。

  1. 在“用户-DSN”选项卡中单击“添加”
  2. 选择:“Microsoft Access Driver”并保存
  3. 为您的新数据源命名(稍后连接数据库时将使用此名称)
  4. 单击“选择”:选择您的访问数据库所在的目录并保存

然后在R中:

library(RODBC)
dcon <- dbConnect(odbc::odbc(), "name-you-gave-to-your-datasource-in-3")
于 2018-11-17T13:40:50.097 回答
0

我正在运行 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;"))
于 2019-07-26T16:30:24.883 回答