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

当我尝试将 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 会话。

标签: r ms-access rodbc


【解决方案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】:

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

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

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

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

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

【讨论】:

    【解决方案3】:

    根据其他人的建议,这是一个将 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】:

      这里有一个函数可以将数据从 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 会稍微安全一些。
      【解决方案5】:

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

      【讨论】:

      • 非常感谢,成功了!
      【解决方案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,";"))
      

      【讨论】:

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

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

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

      1. 在“user-DSN”选项卡中单击“添加”
      2. 选择:“Microsoft Access Driver”并保存
      3. 为您的新数据源命名(稍后连接数据库时将使用此名称)
      4. 点击“选择”:选择您的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;"))
        

        【讨论】:

          猜你喜欢
          • 2013-09-16
          • 2012-05-04
          • 2013-10-20
          • 1970-01-01
          • 2016-09-05
          • 2015-05-06
          • 2018-01-30
          相关资源
          最近更新 更多