PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Wie schreibe ich eine Tabelle in PostgreSQL von R?

Ok, ich bin mir nicht sicher, warum dbWriteTable() würde scheitern; Möglicherweise gibt es eine Art Versions-/Protokollkonflikt. Vielleicht könnten Sie versuchen, die neuesten Versionen von R, das RPostgreSQL-Paket, zu installieren und den PostgreSQL-Server auf Ihrem System zu aktualisieren, falls möglich.

Bezüglich des insert into Problemumgehung für große Datenmengen fehlschlägt, was in der IT-Welt oft getan wird, wenn große Datenmengen verschoben werden müssen und eine One-Shot-Übertragung nicht durchführbar/unpraktisch/unzuverlässig ist, wird manchmal als Batching bezeichnet oder Stapelverarbeitung . Grundsätzlich teilen Sie die Daten in kleinere Blöcke auf und senden jeden Block einzeln.

Als zufälliges Beispiel habe ich vor einigen Jahren einen Java-Code geschrieben, um Mitarbeiterinformationen von einem HR-LDAP-Server abzufragen, der darauf beschränkt war, nur 1000 Datensätze gleichzeitig bereitzustellen. Also musste ich im Grunde eine Schleife schreiben, um immer dieselbe Anfrage zu senden (wobei der Abfragestatus mit eine Art seltsamer Cookie-basierter Mechanismus ) und Sammeln der Datensätze in einer lokalen Datenbank, bis der Server die Abfrage als abgeschlossen gemeldet hat.

Hier ist ein Code, der die SQL manuell erstellt, um eine leere Tabelle basierend auf einem bestimmten data.frame zu erstellen und dann den Inhalt des data.frame mit einer parametrisierten Stapelgröße in die Tabelle einzufügen. Es basiert hauptsächlich auf Aufrufen von paste() zum Erstellen der SQL-Strings und dbSendQuery() um die eigentlichen Anfragen zu senden. Ich verwende auch postgresqlDataType() für die Tabellenerstellung.

## 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

Beachten Sie, dass ich mir nicht die Mühe gemacht habe, row.names voranzustellen -Spalte in die Datenbanktabelle, im Gegensatz zu dbWriteTable() , die immer eine solche Spalte zu enthalten scheint (und anscheinend keine Möglichkeit bietet, dies zu verhindern).