Добре, не съм сигурен защо dbWriteTable()
ще се провали; може да има някакъв вид несъответствие на версия/протокол. Може би можете да опитате да инсталирате най-новите версии на R, пакета RPostgreSQL и да надстроите PostgreSQL сървъра на вашата система, ако е възможно.
Относно insert into
заобиколно решение, неуспешно за големи данни, това, което често се прави в света на ИТ, когато трябва да се преместят големи количества данни и еднократният трансфер е неосъществим/непрактичен/нестабилен, понякога се нарича пакетиране или пакетна обработка
. По принцип разделяте данните на по-малки части и изпращате всяка част една по една.
Като случаен пример, преди няколко години написах някакъв Java код за запитване за информация за служители от HR LDAP сървър, който беше ограничен да предоставя само 1000 записа наведнъж. Така че основно трябваше да напиша цикъл, за да продължа да изпращам същата заявка (като състоянието на заявката се проследява с помощта на някакъв вид странен механизъм, базиран на бисквитки ) и натрупване на записите в локална база данни, докато сървърът отчете, че заявката е завършена.
Ето някакъв код, който ръчно конструира SQL, за да създаде празна таблица на базата на даден data.frame и след това да вмъкне съдържанието на data.frame в таблицата, като използва параметризиран партиден размер. Основно е изграден около извиквания на paste()
за изграждане на SQL низовете и dbSendQuery()
за изпращане на действителните запитвания. Също така използвам postgresqlDataType()
за създаване на таблица.
## 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
Имайте предвид, че не си направих труда да добавя row.names
колона към таблицата на базата данни, за разлика от dbWriteTable()
, която винаги изглежда включва такава колона (и не изглежда предоставя никакви средства за предотвратяването й).