PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Como escrever uma tabela no PostgreSQL do R?


Ok, não sei por que dbWriteTable() estaria falhando; pode haver algum tipo de incompatibilidade de versão/protocolo. Talvez você possa tentar instalar as versões mais recentes do R, o pacote RPostgreSQL e atualizar o servidor PostgreSQL em seu sistema, se possível.

Em relação ao insert into falha de solução alternativa para grandes dados, o que geralmente é feito no mundo de TI quando grandes quantidades de dados devem ser movidas e uma transferência de uma só vez é inviável/impraticável/fraca é o que às vezes é chamado de lote ou processamento em lote . Basicamente, você divide os dados em partes menores e envia cada parte uma de cada vez.

Como um exemplo aleatório, alguns anos atrás, escrevi um código Java para consultar informações de funcionários de um servidor LDAP de RH que era restrito a fornecer apenas 1.000 registros por vez. Então, basicamente, eu tive que escrever um loop para continuar enviando a mesma solicitação (com o estado da consulta rastreado usando algum tipo de mecanismo estranho baseado em cookies ) e acumulando os registros em um banco de dados local até que o servidor informasse que a consulta foi concluída.

Aqui está um código que constrói manualmente o SQL para criar uma tabela vazia com base em um determinado data.frame e, em seguida, insere o conteúdo do data.frame na tabela usando um tamanho de lote parametrizado. É construído principalmente em torno de chamadas para paste() para construir as strings SQL e dbSendQuery() para enviar as consultas reais. Eu também uso postgresqlDataType() para a criação da tabela.
## 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

Observe que não me preocupei em adicionar um row.names coluna para a tabela do banco de dados, ao contrário de dbWriteTable() , que sempre parece incluir essa coluna (e não parece fornecer nenhum meio de impedi-lo).