Dobře, nejsem si jistý, proč dbWriteTable()
by selhal; může dojít k nějakému nesouladu verze/protokolu. Možná byste mohli zkusit nainstalovat nejnovější verze R, balíček RPostgreSQL a upgradovat server PostgreSQL na vašem systému, je-li to možné.
Ohledně insert into
Selhání řešení pro velká data, což se často dělá ve světě IT, když je nutné přesunout velké množství dat a jednorázový přenos je neproveditelný/nepraktický/nefunkční, je to, co se někdy nazývá dávkování nebo dávkové zpracování
. V zásadě rozdělíte data na menší části a odešlete jednotlivé části po jednom.
Jako náhodný příklad jsem před několika lety napsal nějaký kód Java pro dotazování na informace o zaměstnancích ze serveru HR LDAP, který byl omezen na poskytování pouze 1000 záznamů najednou. V zásadě jsem tedy musel napsat smyčku, abych stále posílal stejný požadavek (se stavem dotazu sledovaným pomocí nějaký podivný mechanismus založený na souborech cookie ) a shromažďování záznamů do místní databáze, dokud server neoznámí dokončení dotazu.
Zde je nějaký kód, který ručně zkonstruuje SQL, aby vytvořil prázdnou tabulku založenou na daném data.frame a poté vložil obsah data.frame do tabulky pomocí parametrizované velikosti dávky. Většinou je postaven na voláních paste()
k vytvoření řetězců SQL a dbSendQuery()
k odeslání skutečných dotazů. Také používám postgresqlDataType()
pro vytvoření tabulky.
## 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
Všimněte si, že jsem se neobtěžoval předřadit row.names
na rozdíl od dbWriteTable()
, který takový sloupec vždy obsahuje (a zdá se, že neposkytuje žádné prostředky, jak tomu zabránit).