PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Comment écrire une table dans PostgreSQL à partir de R ?

Ok, je ne sais pas pourquoi dbWriteTable() échouerait ; il peut y avoir une sorte de non-concordance de version/protocole. Vous pourriez peut-être essayer d'installer les dernières versions de R, le package RPostgreSQL et mettre à niveau le serveur PostgreSQL sur votre système, si possible.

Concernant le insert into solution de contournement échouant pour les données volumineuses, ce qui est souvent fait dans le monde informatique lorsque de grandes quantités de données doivent être déplacées et qu'un transfert ponctuel est irréalisable/impraticable/flaky est ce que l'on appelle parfois le traitement par lots ou traitement par lots . Fondamentalement, vous divisez les données en plus petits morceaux et envoyez chaque morceau un à la fois.

À titre d'exemple aléatoire, il y a quelques années, j'ai écrit du code Java pour rechercher des informations sur les employés à partir d'un serveur LDAP RH qui était contraint de ne fournir que 1000 enregistrements à la fois. Donc, fondamentalement, j'ai dû écrire une boucle pour continuer à envoyer la même requête (avec l'état de la requête suivi à l'aide de une sorte de mécanisme étrange basé sur les cookies ) et en accumulant les enregistrements dans une base de données locale jusqu'à ce que le serveur signale que la requête est terminée.

Voici un code qui construit manuellement le SQL pour créer une table vide basée sur un data.frame donné, puis insère le contenu du data.frame dans la table en utilisant une taille de lot paramétrée. Il est principalement construit autour d'appels à paste() pour construire les chaînes SQL, et dbSendQuery() pour envoyer les requêtes réelles. J'utilise aussi postgresqlDataType() pour la création du tableau.

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

Notez que je n'ai pas pris la peine d'ajouter un row.names colonne à la table de la base de données, contrairement à dbWriteTable() , qui semble toujours inclure une telle colonne (et ne semble fournir aucun moyen de l'empêcher).