简体   繁体   English

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

[英]How to connect R with Access database in 64-bit Window?

When I tried to connect R with Access database I get an error当我尝试将 R 与 Access 数据库连接时,出现错误

odbcConnectAccess is only usable with 32-bit Windows

Does anyone has an idea how to solve this?有谁知道如何解决这个问题?

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

Use odbcDriverConnect instead.请改用odbcDriverConnect If you have 64-bit R installed, you may have to use the 32-bit R build.如果您安装了 64 位 R,则可能必须使用 32 位 R 版本。

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

Here is a single function that will transfer data from 32 bit access to 64 bit R without having to save any files.这是一个函数,可以将数据从 32 位访问传输到 64 位 R,而无需保存任何文件。 The function builds an expression string that is passed to a second 32 bit session;该函数构建一个表达式字符串,传递给第二个 32 位会话; data is then returned to the original session using socket server package (svSocket).然后使用套接字服务器包 (svSocket) 将数据返回到原始会话。 One thing to note is that the socket server saves the access data in the global environment so the second parameter is used to define the output instead of using "<-" to save the output.需要注意的一点是,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)
  }
}

Occasionally this function will return an error, but it does not impact data retrieval and appears to result from closing the socket server connection.有时这个函数会返回一个错误,但它不会影响数据检索,并且似乎是由于关闭套接字服务器连接造成的。

There is likely room for improvement, but this provides a simple and quick method to pull data into R from 32 bit access.可能还有改进的余地,但这提供了一种简单快捷的方法,可以将数据从 32 位访问拉入 R。

Did not succeed with the given answers, but here is the step by step approach that eventually did the trick for me.给出的答案没有成功,但这里是一步一步的方法,最终对我有用。 Have Windows 8 on 64 bit.在 64 位上安装 Windows 8。 With 64 and 32 bit R installed.安装了 64 位和 32 位 R。 My Access is 32 bit.我的访问是 32 位。

Steps to use, assuming 32 bit Access on windows 8使用步骤,假设在 Windows 8 上有 32 位访问权限

  1. Select 32 bit R (is just a setting in R studio)选择 32 位 R(只是 R studio 中的一个设置)
  2. search on windows for Set up ODBC data sources (32 bit)在 Windows 上搜索设置 ODBC 数据源(32 位)
  3. Go to System DSN>Add转到系统 DSN>添加
  4. Choose Driver do Microsoft Access (*.mdb) > Finish选择 Driver do Microsoft Access (*.mdb) > Finish
  5. Data source name: ProjecnameAcc数据源名称:ProjecnameAcc
  6. Description: ProjectnameAcc描述:项目名称Acc
  7. Make sure to actually select the database > OK确保实际选择数据库> OK

Now I could run the code that I liked现在我可以运行我喜欢的代码

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

I came across this SO when encountering a similar problem and at this point we have at least one more option with the extremely flexible odbc library.我在遇到类似问题时遇到了这个 SO,此时我们至少还有一个非常灵活的 odbc 库的选择。

An important note here though: the MS Access ODBC driver is not part of a default MS Office installation so you will have to download the appropriate driver from Microsoft (Microsoft Access Database Engine 2016 Redistributable in my case) and be sure to download the appropriate bitness (eg AccessDatabaseEngine_X64.exe).不过这里有一个重要的注意事项:MS Access ODBC 驱动程序不是默认的 MS Office 安装的一部分,因此您必须从 Microsoft(在我的情况下为 Microsoft Access Database Engine 2016 Redistributable)下载适当的驱动程序,并确保下载适当的位数(例如 AccessDatabaseEngine_X64.exe)。 Once that has been downloaded it should automatically show up in your Windows ODBC Data Sources (64-bit) utility or you can confirm inside an R session with the odbcListDrivers function.下载后,它应该会自动显示在您的 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,";"))

Using advice from others, here's an explicit example of getting 32-bit Access data into 64-bit R that you can write into a script so that you don't need to do the steps manually.根据其他人的建议,这里有一个将 32 位 Access 数据导入 64 位 R 的明确示例,您可以将其写入脚本,这样您就无需手动执行这些步骤。 You do need to have 32-bit R available on your machine for this to run, and this script assumes a default location for the 32 bit R, so adjust as needed.您的机器上确实需要有 32 位 R 才能运行,并且此脚本假定 32 位 R 的默认位置,因此请根据需要进行调整。

The first code part goes into your main script, the second code part is the entire contents of a little R script file that you create and is called from the main script, this combination extracts and saves and then loads the data from the access database without having to stop.第一个代码部分进入您的主脚本,第二个代码部分是您创建并从主脚本调用的一个小 R 脚本文件的全部内容,这种组合从 access 数据库中提取并保存然后加载数据,无需不得不停下来。

Here's the bit that goes in my main script, this is run from within 64 bit 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

Here's the bit that is the separate script called GetAccessTables.R这是名为 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)

The function by manotheshark above is very useful, but I wanted to use an SQL query, rather than a table name, to access the database and also to pass the database name as a parameter since I commonly work with a number of Access databases.上面 manotheshark 的函数非常有用,但我想使用 SQL 查询而不是表名来访问数据库并将数据库名作为参数传递,因为我通常使用许多 Access 数据库。 Here is a modified version:这是一个修改后的版本:

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)
  }
}

I also had some difficulty working out how to call manotheshark's function and it took some delving into the svSocket package documentation to realise that the calling script needs to instantiate the object in which the data will be returned and then to pass its NAME (not the object itself) in the table_out parameter.我在弄清楚如何调用 manotheshark 的函数时也遇到了一些困难,我深入研究了 svSocket 包文档,才意识到调用脚本需要实例化将返回数据的对象,然后传递其 NAME(而不是对象本身)在 table_out 参数中。 Here is an example of an R-script that calls my modified version:这是调用我的修改版本的 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")

This works, but has limitations.这有效,但有局限性。

Firstly, avoid any Microsoft Access SQL extensions.首先,避免任何 Microsoft Access SQL 扩展。 For example, if you use the Access Query builder, it will often insert field names like [TABLE_NAME]![FIELD_NAME] .例如,如果您使用 Access Query builder,它通常会插入字段名称,如[TABLE_NAME]![FIELD_NAME] These will not work.这些都行不通。 Also Access allows non-standard field names that start with a digit like "10kmSq" and allows you to use them in SQL like SELECT [10kmSq] FROM ... . Access 还允许以“10kmSq”等数字开头的非标准字段名称,并允许您在 SQL 中使用它们,如SELECT [10kmSq] FROM ... This also won't work.这也行不通。 If there is an error in the SQL syntax, the return variable will contain an error message.如果 SQL 语法有错误,则返回变量将包含错误消息。

Secondly, the amount of data you can return appears to be limited to 64Kb.其次,您可以返回的数据量似乎仅限于 64Kb。 If you try to run SQL that returns too much, the 32-bit session does not terminate and the script hangs.如果您尝试运行返回过多的 SQL,则 32 位会话不会终止并且脚本挂起。

The following solution worked for me: found on reading-data-from-32-bit-access-db-using-64-bit-R It says to install the 64-bit database engine from: microsoft `以下解决方案对我有用:在reading-data-from-32-bit-access-db-using-64-bit-R 上找到它说要从以下位置安装 64 位数据库引擎: microsoft `

Then: find and run "ODBC-datasources (64-bits)".然后:找到并运行“ODBC-datasources (64-bits)”。

  1. In the tab "user-DSN" click "Add"在“用户-DSN”选项卡中单击“添加”
  2. Select: "Microsoft Access Driver" and save选择:“Microsoft Access Driver”并保存
  3. Give your new datasource a name (you will use this name when connecting to the database later)为您的新数据源命名(稍后连接到数据库时将使用此名称)
  4. Click "Select": Select the directory where your access database(s) exist and save单击“选择”:选择您的访问数据库所在的目录并保存

Then in R:然后在R中:

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

I am running Windows 10 x64, Office 365 x64 (not sure that is relevant), and R 64-bit.我正在运行 Windows 10 x64、Office 365 x64(不确定是否相关)和 R 64 位。 I did not need to switch to 32-bit R.我不需要切换到 32 位 R。

In my case, I got it working by installing the 64-bit version of the Microsoft Access Database Engine 2016 Redistributable and then by giving my own account, which rsession.exe runs as, Full Control permissions on the HKEY_LOCAL_MACHINE\\SOFTWARE\\ODBC registry key.在我的情况下,我通过安装 64 位版本的Microsoft Access Database Engine 2016 Redistributable然后通过提供我自己的帐户(rsession.exe 运行为)对HKEY_LOCAL_MACHINE\\SOFTWARE\\ODBC注册表项的完全控制权限来使其工作.

The permissions on registry key make no sense.注册表项的权限没有意义。 My account is already a member of this PC's Administrators group, and that group already has Full Control permission on that key.我的帐户已经是这台 PC 的管理员组的成员,并且该组已经对该密钥具有完全控制权限。

The commands I used:我使用的命令:

library("odbc")

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM