sql >> Database teknologi >  >> RDS >> PostgreSQL

Hvordan skriver man en tabel i PostgreSQL fra R?

Ok, jeg er ikke sikker på hvorfor dbWriteTable() ville fejle; der kan være en form for version/protokol uoverensstemmelse. Måske kan du prøve at installere de nyeste versioner af R, RPostgreSQL-pakken og opgradere PostgreSQL-serveren på dit system, hvis det er muligt.

Med hensyn til insert into løsning, der mislykkes for store data, hvad der ofte gøres i it-verdenen, når store mængder data skal flyttes, og en one-shot-overførsel er uigennemførlig/upraktisk/flaky, er det, der nogle gange omtales som batching eller batchbehandling . Grundlæggende deler du dataene op i mindre bidder og sender hver chunk en ad gangen.

Som et tilfældigt eksempel skrev jeg for et par år siden noget Java-kode for at forespørge efter medarbejderoplysninger fra en HR LDAP-server, som var begrænset til kun at levere 1000 poster ad gangen. Så dybest set var jeg nødt til at skrive en loop for at blive ved med at sende den samme anmodning (med forespørgselstilstanden sporet ved hjælp af en slags mærkelig cookie-baseret mekanisme ) og akkumulere posterne i en lokal database, indtil serveren rapporterede, at forespørgslen var fuldført.

Her er noget kode, der manuelt konstruerer SQL'en for at skabe en tom tabel baseret på en given data.frame, og derefter indsætte indholdet af data.frame i tabellen ved hjælp af en parametriseret batchstørrelse. Det er for det meste bygget op omkring kald til paste() for at bygge SQL-strengene og dbSendQuery() at sende de faktiske forespørgsler. Jeg bruger også postgresqlDataType() til tabeloprettelse.

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

Bemærk, at jeg ikke gad at sætte en row.names foran kolonne til databasetabellen, i modsætning til dbWriteTable() , som altid lader til at indeholde en sådan kolonne (og lader ikke til at give nogen måde at forhindre det på).



  1. Hjælp med en MySql-forespørgsel - Rækkerne holder det gruppemæssige maksimum af en bestemt kolonne

  2. Hvordan får man et tidsstempel i Java og gemmer i MySQL-databasen?

  3. få næste og forrige id-post i databasen på Yii

  4. Oracle SQLPlus ORA-01017 ugyldige legitimationsoplysninger ved angivelse af skema