web-dev-qa-db-fra.com

Comment connecter la base de données R avec Access dans une fenêtre 64 bits?

Lorsque j'ai essayé de connecter R avec la base de données Access, un message d'erreur s'affiche. 

odbcConnectAccess is only usable with 32-bit Windows

Quelqu'un a-t-il une idée de comment résoudre ce problème?

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

Utilisez odbcDriverConnect à la place. Si vous avez installé la version 64 bits, vous devrez peut-être utiliser la version 32 bits.

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

Voici une fonction unique qui transférera des données d’un accès 32 bits à un R 64 bits sans avoir à enregistrer de fichiers. La fonction crée une chaîne d'expression qui est transmise à une seconde session 32 bits. les données sont ensuite renvoyées à la session d'origine à l'aide du package de serveur de socket (svSocket). Une chose à noter est que le serveur de socket sauvegarde les données d'accès dans l'environnement global. Le second paramètre est donc utilisé pour définir la sortie au lieu d'utiliser "<-" pour enregistrer la sortie.

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

Parfois, cette fonction renvoie une erreur, mais cela n’affecte pas la récupération des données et semble résulter de la fermeture de la connexion au serveur de socket.

Des améliorations sont vraisemblablement possibles, mais cela fournit une méthode simple et rapide pour extraire des données en accès R de 32 bits.

11
manotheshark

N'a pas réussi avec les réponses données, mais voici l'approche étape par étape qui a finalement fait l'affaire pour moi. Avoir Windows 8 sur 64 bits. Avec 64 et 32 ​​bits R installés. Mon accès est 32 bits.

Procédure à suivre en supposant un accès 32 bits sous Windows 8

  1. Sélectionnez 32 bits R (est juste un paramètre dans R studio)
  2. recherche sur les fenêtres pour configurer les sources de données ODBC (32 bits)
  3. Aller au DSN système> Ajouter
  4. Choisissez Driver do Microsoft Access (* .mdb)> Terminer
  5. Nom de la source de données: ProjecnameAcc
  6. Description: ProjectnameAcc
  7. Assurez-vous de bien sélectionner la base de données> OK

Maintenant, je pourrais exécuter le code que j'ai aimé

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

À l'aide des conseils d'autres personnes, voici un exemple explicite d'obtention de données Access 32 bits en R 64 bits que vous pouvez écrire dans un script afin que vous n'ayez pas à suivre cette procédure manuellement. Pour que cette opération s'exécute, vous devez disposer de la version 32 bits R disponible sur votre ordinateur. Ce script suppose un emplacement par défaut pour la version 32 bits R. Réglez donc si nécessaire. 

La première partie de code va dans votre script principal, la seconde partie de code contient tout le contenu d'un petit fichier de script R créé et appelé à partir du script principal. Cette combinaison extrait et enregistre, puis charge les données de la base de données d'accès sans avoir à arrêter. 

Voici le bit qui va dans mon script principal, il est exécuté à partir de 64 bits 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

Voici le bit qui est le script séparé appelé 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)
2
jNorris

Je suis tombé sur ce SO en rencontrant un problème similaire. À ce stade, nous avons au moins une option supplémentaire avec la bibliothèque odbc extrêmement flexible.

Une remarque importante ici cependant: le pilote MS Access ODBC ne fait pas partie d’une installation MS Office par défaut. Vous devrez donc télécharger le pilote approprié à partir de Microsoft (Microsoft Access Database Engine 2016 Redistributable dans mon cas) et vous assurer de téléchargez le bitness approprié (par exemple AccessDatabaseEngine_X64.exe). Une fois celui-ci téléchargé, il devrait s'afficher automatiquement dans votre utilitaire de sources de données Windows ODBC (64 bits) ou vous pouvez confirmer à l'intérieur d'une session R avec la fonction 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,";"))
1

La fonction de manotheshark ci-dessus est très utile, mais je voulais utiliser une requête SQL, plutôt qu'un nom de table, pour accéder à la base de données et également passer le nom de la base de données en tant que paramètre car je travaille couramment avec plusieurs bases de données Access. Voici une version modifiée:

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

J'ai également eu quelques difficultés à comprendre comment appeler la fonction de manotheshark et il a fallu quelques explications dans la documentation du paquet svSocket pour comprendre que le script appelant doit instancier l'objet dans lequel les données seront renvoyées, puis transmettre son nom (et non l'objet). lui-même) dans le paramètre table_out. Voici un exemple de R-script qui appelle ma version modifiée:

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

Cela fonctionne, mais a des limites. 

Tout d’abord, évitez toute extension Microsoft Access SQL. Par exemple, si vous utilisez le générateur Requête d'accès, il insère souvent des noms de champ tels que [TABLE_NAME]![FIELD_NAME]. Cela ne fonctionnera pas. Access autorise également les noms de champs non standard commençant par un chiffre tel que "10kmSq" et vous permet de les utiliser en SQL comme SELECT [10kmSq] FROM .... Cela ne fonctionnera pas non plus. En cas d'erreur dans la syntaxe SQL, la variable de retour contiendra un message d'erreur.

Deuxièmement, la quantité de données que vous pouvez renvoyer semble être limitée à 64 Ko. Si vous essayez d'exécuter du SQL qui retourne trop, la session 32 bits ne se termine pas et le script se bloque.

1
Stuart Ball

La solution suivante a fonctionné pour moi: trouvée sur reading-data-from-32-bit-access-db-using-64-bit-R Il est dit d’installer le moteur de base de données 64 bits depuis: Microsoft `

Ensuite: recherchez et exécutez "sources de données ODBC (64 bits)". 

  1. Dans l'onglet "utilisateur-DSN", cliquez sur "Ajouter".
  2. Sélectionnez: "Microsoft Access Driver" et enregistrez
  3. Donnez un nom à votre nouvelle source de données (vous utiliserez ce nom lors de votre prochaine connexion à la base de données)
  4. Cliquez sur "Sélectionner": sélectionnez le répertoire contenant votre (vos) base (s) d'accès et sauvegardez 

Puis dans R:

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