sql >> Base de Datos >  >> RDS >> PostgreSQL

¿Cómo escribir una tabla en PostgreSQL desde R?

Ok, no estoy seguro de por qué dbWriteTable() estaría fallando; puede haber algún tipo de discrepancia de versión/protocolo. Tal vez podría intentar instalar las últimas versiones de R, el paquete RPostgreSQL y actualizar el servidor PostgreSQL en su sistema, si es posible.

Con respecto a insert into la solución alternativa falla para grandes cantidades de datos, lo que a menudo se hace en el mundo de TI cuando se deben mover grandes cantidades de datos y una transferencia única es inviable/poco práctica/escamosa es lo que a veces se denomina procesamiento por lotes o procesamiento por lotes . Básicamente, divide los datos en fragmentos más pequeños y envía cada fragmento uno a la vez.

Como ejemplo aleatorio, hace algunos años escribí un código Java para consultar la información de los empleados de un servidor LDAP de recursos humanos que estaba limitado a proporcionar solo 1000 registros a la vez. Básicamente, tuve que escribir un bucle para seguir enviando la misma solicitud (con el estado de la consulta rastreado usando algún tipo de mecanismo extraño basado en cookies ) y acumulando los registros en una base de datos local hasta que el servidor informó que la consulta se completó.

Aquí hay un código que construye manualmente el SQL para crear una tabla vacía basada en un marco de datos dado, y luego inserta el contenido del marco de datos en la tabla usando un tamaño de lote parametrizado. Se basa principalmente en llamadas a paste() para construir las cadenas SQL y dbSendQuery() para enviar las consultas reales. También uso postgresqlDataType() para la creación de la tabla.

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

Tenga en cuenta que no me molesté en anteponer un row.names columna a la tabla de la base de datos, a diferencia de dbWriteTable() , que siempre parece incluir dicha columna (y no parece proporcionar ningún medio para evitarlo).