如何在 64 位窗口中将 R 与 Access 数据库连接?

Posted

技术标签:

【中文标题】如何在 64 位窗口中将 R 与 Access 数据库连接?【英文标题】:How to connect R with Access database in 64-bit Window? 【发布时间】:2012-10-25 14:21:35 【问题描述】:

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

odbcConnectAccess is only usable with 32-bit Windows

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

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

【问题讨论】:

也许this 的回答也可能有帮助,我不确定。 谢谢乔兰。我会尝试这两种选择。 它适用于 32 位。谢谢。 此错误不是由 Windows 安装引起的,但如果您安装了 32 位 Office 并尝试使用 64 位 R。我在下面添加了一个脚本,它将启动第二个 32-位 R 会话从 32 位 Access 读取数据,然后将数据复制回原始 64 位 R 会话。 【参考方案1】:

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

odbcDriverConnect("Driver=Microsoft Access Driver (*.mdb, *.accdb);DBQ=D:/SampleDB1/sampleDB1.mdb")

【讨论】:

谢谢您。我刚试了一下,报了一行错误:( 是的,我使用的是 64 位 R。如果有帮助,我会将其更改为 32 位。 是的,我现在将其更改为 32 位 R 并且它正在工作。感谢您的提示。 我正在尝试这个,但我仍然面临同样的问题。它连接到亚马逊的数据库但无法访问 安装 AccessDatabaseEngine_x64.exe 对我有用【参考方案2】:

这里有一个函数可以将数据从 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 中。

【讨论】:

使用prog &lt;- file.path(R.home(), "bin", "i386", "Rscript.exe") 避免依赖R_HOME 会稍微安全一些。【参考方案3】:

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

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

    选择 32 位 R(只是 R studio 中的一个设置) 在 Windows 上搜索设置 ODBC 数据源(32 位) 转到系统 DSN>添加 选择驱动程序执行 Microsoft Access (*.mdb) > 完成 数据源名称:ProjecnameAcc 描述:项目名称Acc 确保实际选择数据库 > 确定

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

channel <- odbcConnect("ProjectnameAcc")
Table1Dat <- sqlFetch(channel, "Table1")

【讨论】:

【参考方案4】:

我在遇到类似问题时遇到了这个 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,";"))

【讨论】:

这在 Windows 10 上对我有用。如果它不起作用,请运行 odbcListDrivers()。如果“Microsoft Access Driver (*.mdb, *.accdb)”没有出现,您将需要安装上面讨论的 Access 可再发行组件。当我尝试安装 AccessDatabaseEngine_X64.exe 时,我收到有关“Office 16 Click-to-Run Extensibility Component”冲突的错误。我能够按照错误消息上的说明解决此冲突。安装后,当我在 R 中运行 odbcListDrivers() 时,就会出现驱动程序。【参考方案5】:

根据其他人的建议,这是一个将 32 位 Access 数据转换为 64 位 R 的明确示例,您可以将其写入脚本中,这样您就无需手动执行这些步骤。您确实需要在您的机器上安装 32 位 R 才能运行此脚本,并且此脚本假定 32 位 R 的默认位置,因此请根据需要进行调整。

第一个代码部分进入您的主脚本,第二个代码部分是您创建并从主脚本调用的一个小 R 脚本文件的全部内容,此组合提取并保存然后从无需停止即可访问数据库。

这是我的主脚本中的部分,这是从 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)

【讨论】:

【参考方案6】:

上面 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 包文档才意识到调用脚本需要实例化返回数据的对象,然后传递它的 NAME (不是对象本身)在 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 扩展。例如,如果您使用“访问查询”构建器,它通常会插入像 [TABLE_NAME]![FIELD_NAME] 这样的字段名称。这些都行不通。 Access 还允许以“10kmSq”之类的数字开头的非标准字段名称,并允许您在 SQL 中使用它们,例如SELECT [10kmSq] FROM ...。这也行不通。如果 SQL 语法有错误,返回变量将包含错误消息。

其次,您可以返回的数据量似乎限制为 64Kb。如果您尝试运行返回过多的 SQL,则 32 位会话不会终止并且脚本会挂起。

【讨论】:

非常感谢,成功了!【参考方案7】:

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

然后:找到并运行“ODBC 数据源(64 位)”。

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

然后在 R 中:

library(RODBC)
dcon <- dbConnect(odbc::odbc(), "name-you-gave-to-your-datasource-in-3")

【讨论】:

【参考方案8】:

我正在运行 Windows 10 x64、Office 365 x64(不确定是否相关)和 R 64 位。我不需要切换到 32 位 R。

在我的例子中,我通过安装 64 位版本的 Microsoft Access Database Engine 2016 Redistributable 然后给我自己的帐户(rsession.exe 运行为)提供对HKEY_LOCAL_MACHINE\SOFTWARE\ODBC 注册表项。

注册表项的权限没有意义。我的帐户已经是这台电脑的 Administrators 组的成员,并且该组已经对该密钥具有完全控制权限。

我使用的命令:

library("odbc")

accdb_con <- dbConnect(drv = odbc(), .connection_string = paste0("Driver=Microsoft Access Driver (*.mdb, *.accdb);DBQ=C:/full_path_to_file/buildings.mdb;"))

【讨论】:

以上是关于如何在 64 位窗口中将 R 与 Access 数据库连接?的主要内容,如果未能解决你的问题,请参考以下文章

addq 与 64 位立即数?

使用 c# 在 32 位和 64 位窗口中打开 ms-access .mdb

如何在R中生成随机的64位十六进制数?

如何在未知大小的二进制数中将所有位设置为“1”?

MS Access 的 ODBC 驱动程序似乎丢失(Windows 64 位)

如何在 VB 中检索 64 位/Access 2013 的 Windows 用户 ID?