Jak połączyć R z bazą danych Access W 64-bitowym oknie?
Kiedy próbowałem połączyć R z bazą danych Access dostaję błąd
odbcConnectAccess is only usable with 32-bit Windows
Czy ktoś ma pomysł jak to rozwiązać?
library(RODBC)
mdbConnect<-odbcConnectAccess("D:/SampleDB1/sampleDB1.mdb")
6 answers
Zamiast tego użyj odbcDriverConnect
. Jeśli masz zainstalowany 64-bitowy r, być może będziesz musiał użyć 32-bitowej kompilacji R.
odbcDriverConnect("Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=D:/SampleDB1/sampleDB1.mdb")
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-25 14:39:36
Oto jedna funkcja, która będzie przesyłać dane z 32-bitowego dostępu do 64-bitowego R bez konieczności zapisywania żadnych plików. Funkcja buduje łańcuch wyrażeń, który jest przekazywany do drugiej 32-bitowej sesji; dane są następnie zwracane do oryginalnej sesji za pomocą pakietu socket server (svSocket). Należy zauważyć, że serwer socket zapisuje dane dostępowe w środowisku globalnym, więc drugi parametr jest używany do definiowania wyjścia zamiast używania "
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)
}
}
Czasami ta funkcja zwróci błąd, ale nie wpływa na pobieranie danych i wydaje się wynikać z zamknięcia połączenia z serwerem gniazda.
Jest prawdopodobnie miejsce na poprawę, ale zapewnia to prostą i szybką metodę pobierania danych do R z dostępu 32-bitowego.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-21 20:10:05
Nie udało się z udzielonymi odpowiedziami, ale tutaj jest podejście krok po kroku, które ostatecznie zrobił sztuczkę dla mnie. Miej Windows 8 na bitach 64. Z zainstalowanym 64 i 32-bitowym R. Mój Dostęp to 32 bit.
Kroki do użycia, zakładając dostęp 32-bitowy w systemie windows 8
- Select 32 bit R (is just a setting in R studio)
- wyszukaj w systemie windows skonfigurowane źródła danych ODBC (32-bitowe)
- przejdź do systemu DSN>Dodaj
- Wybierz sterownik do Microsoft Access (*.mdb) > Finish
- Nazwa źródła danych: ProjecnameAcc
- Opis: ProjectnameAcc
- Upewnij się, że faktycznie wybierz bazę danych > OK
Teraz mogę uruchomić kod, który mi się podobał
channel <- odbcConnect("ProjectnameAcc")
Table1Dat <- sqlFetch(channel, "Table1")
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-21 11:47:49
Korzystając z porad innych, oto wyraźny przykład uzyskania 32-bitowych danych dostępowych do 64-bitowego R, które można zapisać w skrypcie, dzięki czemu nie trzeba wykonywać tych kroków ręcznie. Musisz mieć 32-bitowy R dostępny na komputerze, aby to uruchomić, a ten skrypt przyjmuje domyślną lokalizację dla 32-bitowego R, więc dostosuj w razie potrzeby.
Pierwsza część kodu trafia do głównego skryptu, druga część kodu to cała zawartość małego pliku skryptu R, który tworzysz i jest wywołana ze skryptu głównego, ta kombinacja wyodrębnia i zapisuje, a następnie ładuje dane z bazy danych access bez konieczności zatrzymywania się.
Oto bit, który idzie w moim skrypcie głównym, to jest uruchamiany z wewnątrz 64 bit 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
Oto bit, który jest oddzielnym skryptem o nazwie 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)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-11 15:04:34
Powyższa funkcja manotheshark jest bardzo przydatna, ale chciałem użyć zapytania SQL, a nie nazwy tabeli, aby uzyskać dostęp do bazy danych, a także przekazać nazwę bazy danych jako parametr, ponieważ zwykle pracuję z wieloma bazami danych Access. Oto zmodyfikowana wersja:
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)
}
}
Miałem też pewne trudności z rozpracowaniem sposobu wywołania funkcji manotheshark i wymagało to trochę zagłębienia się w dokumentację pakietu svSocket, aby uświadomić sobie, że skrypt wywołujący musi utworzyć instancję obiekt, w którym zostaną zwrócone dane, a następnie przekazać swoją nazwę (nie sam obiekt) w parametrze table_out. Oto przykład skryptu R, który wywołuje moją zmodyfikowaną wersję:
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")
To działa, ale ma ograniczenia.
Po pierwsze, unikaj rozszerzeń Microsoft Access SQL. Na przykład, jeśli używasz Kreatora zapytań dostępu, często wstawia on nazwy pól, takie jak [TABLE_NAME]![FIELD_NAME]
. To nie zadziała. Access umożliwia również niestandardowe nazwy pól zaczynające się od cyfry, takie jak "10kmsq" i pozwala używać ich w SQL jak SELECT [10kmSq] FROM ...
. To też nie zadziała. Jeżeli w składni SQL występuje błąd, zmienna zwrotna będzie zawierać komunikat o błędzie.
Po drugie, ilość danych, które możesz zwrócić, wydaje się być ograniczona do 64Kb. Jeśli spróbujesz uruchomić SQL, który zwróci zbyt dużo, sesja 32-bitowa nie zostanie zakończona, a skrypt zawiesi się.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-31 11:47:13
Natknąłem się na to, więc napotykając podobny problem i w tym momencie mamy jeszcze co najmniej jedną opcję z niezwykle elastyczną biblioteką odbc.
Ważna uwaga: sterownik MS Access ODBC nie jest częścią domyślnej instalacji MS Office, więc będziesz musiał pobrać odpowiedni sterownik z Microsoft (Microsoft Access Database Engine 2016 Redistributable w moim przypadku) i pamiętaj, aby pobrać odpowiedni bitness (np AccessDatabaseEngine_X64.exe). Raz pobrany plik powinien automatycznie pojawić się w źródłach danych systemu Windows ODBC (64-bit) lub możesz potwierdzić wewnątrz sesji r za pomocą funkcji 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,";"))
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-30 11:55:28