Ok, nie wiem dlaczego dbWriteTable()
upadnie; może występować pewna niezgodność wersji/protokołu. Być może możesz spróbować zainstalować najnowsze wersje R, pakiet RPostgreSQL i zaktualizować serwer PostgreSQL w swoim systemie, jeśli to możliwe.
Odnośnie insert into
nieskuteczne obejście dla dużych danych, co często robi się w świecie IT, gdy duże ilości danych muszą zostać przeniesione, a jednorazowy transfer jest niewykonalny/niepraktyczny/niestabilny, jest czasem określany jako partiami lub przetwarzanie wsadowe
. Zasadniczo dzielisz dane na mniejsze porcje i wysyłasz każdą porcję pojedynczo.
Jako przypadkowy przykład, kilka lat temu napisałem kod w Javie do wyszukiwania informacji o pracownikach z serwera HR LDAP, który był ograniczony do dostarczania tylko 1000 rekordów na raz. Więc w zasadzie musiałem napisać pętlę, aby nadal wysyłać to samo żądanie (ze stanem zapytania śledzonym za pomocą jakiś rodzaj dziwnego mechanizmu opartego na plikach cookie ) i gromadzenie rekordów w lokalnej bazie danych, dopóki serwer nie zgłosi zakończenia zapytania.
Oto kod, który ręcznie konstruuje kod SQL, aby utworzyć pustą tabelę na podstawie danego data.frame, a następnie wstawić zawartość data.frame do tabeli przy użyciu sparametryzowanego rozmiaru partii. Jest głównie zbudowany wokół wywołań paste()
do budowania ciągów SQL i dbSendQuery()
do wysyłania rzeczywistych zapytań. Używam również postgresqlDataType()
do tworzenia tabeli.
## connect to the DB
library('RPostgreSQL'); ## loads DBI automatically
drv <- dbDriver('PostgreSQL');
con <- dbConnect(drv,host=...,port=...,dbname=...,user=...,password=...);
## define helper functions
createEmptyTable <- function(con,tn,df) {
sql <- paste0("create table \"",tn,"\" (",paste0(collapse=',','"',names(df),'" ',sapply(df[0,],postgresqlDataType)),");");
dbSendQuery(con,sql);
invisible();
};
insertBatch <- function(con,tn,df,size=100L) {
if (nrow(df)==0L) return(invisible());
cnt <- (nrow(df)-1L)%/%size+1L;
for (i in seq(0L,len=cnt)) {
sql <- paste0("insert into \"",tn,"\" values (",do.call(paste,c(sep=',',collapse='),(',lapply(df[seq(i*size+1L,min(nrow(df),(i+1L)*size)),],shQuote))),");");
dbSendQuery(con,sql);
};
invisible();
};
## generate test data
NC <- 1e2L; NR <- 1e3L; df <- as.data.frame(replicate(NC,runif(NR)));
## run it
tn <- 't1';
dbRemoveTable(con,tn);
createEmptyTable(con,tn,df);
insertBatch(con,tn,df);
res <- dbReadTable(con,tn);
all.equal(df,res);
## [1] TRUE
Zauważ, że nie zawracałem sobie głowy dodawaniem row.names
kolumna do tabeli bazy danych, w przeciwieństwie do dbWriteTable()
, który zawsze wydaje się zawierać taką kolumnę (i nie wydaje się zapewniać żadnych środków, aby temu zapobiec).