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

时间:2012-10-25 14:21:35

标签: r ms-access rodbc

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

odbcConnectAccess is only usable with 32-bit Windows

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

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

8 个答案:

答案 0 :(得分:23)

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

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

答案 1 :(得分:12)

这是一个单一的功能,可以将数据从32位访问传输到64位R而无需保存任何文件。该函数构建一个传递给第二个32位会话的表达式字符串;然后使用套接字服务器包(svSocket)将数据返回到原始会话。需要注意的一点是套接字服务器将访问数据保存在全局环境中,因此第二个参数用于定义输出,而不是使用“&lt; - ”来保存输出。

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中。

答案 2 :(得分:7)

对于给定的答案没有成功,但这是一步一步的方法,最终为我做了诀窍。在64位上安装Windows 8。安装了64位和32位R。我的访问权限是32位。

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

  1. 选择32位R(只是R studio中的设置)
  2. 在Windows上搜索以设置ODBC数据源(32位)
  3. 转到系统DSN&gt;添加
  4. 选择驱动程序执行Microsoft Access(* .mdb)&gt;完成
  5. 数据来源名称:ProjecnameAcc
  6. 描述:ProjectnameAcc
  7. 确保实际选择数据库&gt;行
  8. 现在我可以运行我喜欢的代码

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

答案 3 :(得分:2)

使用其他人的建议,这里有一个将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)

答案 4 :(得分:2)

遇到类似问题时,我碰到了这种情况,因此,我们现在可以使用非常灵活的odbc库至少有一个选择。

这里有个重要的注意事项:MS Access ODBC驱动程序不是默认MS Office安装的一部分,因此您必须从Microsoft下载合适的驱动程序(在我的情况下为Microsoft Access Database Engine 2016 Redistributable),并确保下载适当的位数(例如AccessDatabaseEngine_X64.exe)。下载完成后,它应该会自动显示在Windows ODBC数据源(64位)实用程序中,或者您可以使用odbcListDrivers函数在R会话中进行确认。

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,";"))

答案 5 :(得分:1)

上面的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参数中传递其NAME(不是对象本身)。以下是调用我修改版本的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也允许非标准字段名称以&#34; 10kmSq&#34;等数字开头。并允许您在SQL SELECT [10kmSq] FROM ...中使用它们。这也不会奏效。如果SQL语法中存在错误,则返回变量将包含错误消息。

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

答案 6 :(得分:1)

以下解决方案对我有用:在reading-data-from-32-bit-access-db-using-64-bit-R上找到 它说要从microsoft`

安装64位数据库引擎。

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

  1. 在“用户DSN”标签中,点击“添加”
  2. 选择:“ Microsoft Access驱动程序”并保存
  3. 给新数据源一个名称(稍后连接数据库时将使用该名称)
  4. 单击“选择”:选择访问数据库所在的目录并保存

然后在R中

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

答案 7 :(得分: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;"))