sql >> Databasteknik >  >> RDS >> PostgreSQL

Hur man skriver en tabell i PostgreSQL från R?

Ok, jag är inte säker på varför dbWriteTable() skulle misslyckas; det kan finnas någon typ av version/protokoll som inte matchar. Du kanske kan testa att installera de senaste versionerna av R, RPostgreSQL-paketet och om möjligt uppgradera PostgreSQL-servern på ditt system.

Angående insert into lösning som misslyckas för stora data, vad som ofta görs i IT-världen när stora mängder data måste flyttas och en engångsöverföring är omöjlig/opraktisk/flaky är vad som ibland kallas batching eller batchbearbetning . I grund och botten delar du upp data i mindre bitar och skickar varje bit en i taget.

Som ett slumpmässigt exempel skrev jag för några år sedan lite Java-kod för att fråga efter anställd information från en HR LDAP-server som var begränsad till att bara tillhandahålla 1000 poster åt gången. Så i princip var jag tvungen att skriva en loop för att fortsätta skicka samma begäran (med frågetillståndet spårat med någon sorts konstig cookie-baserad mekanism ) och ackumulerar posterna i en lokal databas tills servern rapporterade att frågan är klar.

Här är lite kod som manuellt konstruerar SQL för att skapa en tom tabell baserat på en given data.frame, och sedan infoga innehållet i data.frame i tabellen med hjälp av en parametriserad batchstorlek. Det är mestadels byggt kring anrop till paste() för att bygga SQL-strängarna och dbSendQuery() för att skicka de faktiska frågorna. Jag använder också postgresqlDataType() för tabellskapandet.

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

Observera att jag inte brydde mig om att lägga fram en row.names kolumnen till databastabellen, till skillnad från dbWriteTable() , som alltid tycks inkludera en sådan kolumn (och inte verkar ge något sätt att förhindra det).



  1. Null Pointer Undantag vid anrop av getReadableDatabase()

  2. Oracle:hur man subtraherar två datum och får minuter av resultatet

  3. Hur hanterar man valfria parametrar i SQL-fråga?

  4. 9 riktigt användbara MySQL-datumfunktioner som är lätta att komma ihåg