2016-06-06 3 views
1

현재 PostgreSQL 테이블에 데이터를 삽입하려면 빈 테이블을 만들고 insert into table values ...과 함께 모든 값을 가진 단일 문자열을 데이터 스테이지와 함께 축소해야합니다. 대형 데이터 프레임에서는 작동하지 않습니다. 전에 물어 비슷한 질문에 대답 제안 나는 다음과 같은 해킹을 시도R에서 PostgreSQL에 테이블을 쓰는 방법?

Error in postgresqlpqExec(new.con, sql4) : RS-DBI driver: (could not Retrieve the result : ERROR: syntax error at or near "STDIN" LINE 1: COPY "table_1" FROM STDIN 

dbWtriteTable()는 PostgreSQL을 위해 일 다음과 같은 오류를 제공하지 않습니다

.... 여기에 링크가 있습니다 ... How do I write data from R to PostgreSQL tables with an autoincrementing primary key?

body_lines <- deparse(body(RPostgreSQL::postgresqlWriteTable)) 
new_body_lines <- sub(
    'postgresqlTableRef(name), "FROM STDIN")', 
    'postgresqlTableRef(name), "(", paste(shQuote(names(value)), collapse = ","), ") FROM STDIN")', 
    body_lines, 
    fixed = TRUE 
) 
fn <- RPostgreSQL::postgresqlWriteTable 
body(fn) <- parse(text = new_body_lines) 
while("RPostgreSQL" %in% search()) detach("package:RPostgreSQL") 
assignInNamespace("postgresqlWriteTable", fn, "RPostgreSQL") 

이 핵은 여전히 ​​저에게 적합하지 않습니다. postgresqlWriteTable()은 똑같은 오류를 던졌습니다 ... 정확히 여기서 문제가 있습니까?

대안으로 나는 caroline 패키지의 dbWriteTable2()을 사용해 보았습니다. 그리고 직접 PostgreSQL의에서 테이블에 큰 dataframe를 작성하는 다른 방법은 거기에 다른 오류 ...

Error in postgresqlExecStatement(conn, statement, ...) : 
    RS-DBI driver: (could not Retrieve the result : ERROR: column "id" does not exist in table_1 
) 
creating NAs/NULLs for for fields of table that are missing in your df 
Error in postgresqlExecStatement(conn, statement, ...) : 
    RS-DBI driver: (could not Retrieve the result : ERROR: column "id" does not exist in table_1 
) 

던져?

+0

얼마나 큰 이야기입니까? 방금 RPostgresQL :: dbWriteTable()을 사용하여 PostgreSQL 테이블에 R에서 ~ 800MB 10,000x1000 data.frame을 성공적으로 썼습니다. 그것은 (내가 생각하는 한 시간에 접근하는) 시간이 좀 걸렸지 만 효과가있었습니다. – bgoldst

+0

@bgoldst 큰 데이터의 경우'insert into '메소드가 실패했다. 작은 데이터 (1X1 df) 일지라도'dbWriteTable()'이 실패하고 명시된대로 오류를 준다. – Gaurav

답변

1

그래, 왜 dbWriteTable()이 실패할지 잘 모르겠다. 어떤 종류의 버전/프로토콜 불일치가있을 수 있습니다. 가능한 경우 최신 버전의 R, RPostgreSQL 패키지를 설치하고 시스템에서 PostgreSQL 서버를 업그레이드 할 수 있습니다. 대용량 데이터에 대한 실패한 insert into 해결 방법에 대해서는

, 많은 양의 데이터를 이동해야 할 때 무슨 일이 종종 IT 세계에서 수행되고 원샷 전송/불가능 불가능하다/색다른는 배치라고도합니다 것입니다 또는 batch processing. 기본적으로 데이터를 작은 청크로 나누고 각 청크를 한 번에 하나씩 보냅니다.

예를 들어 몇 년 전만해도 한 번에 1000 개의 레코드 만 제공하도록 제한된 HR LDAP 서버에서 직원 정보를 쿼리하는 Java 코드를 작성했습니다. 그래서 기본적으로 (쿼리 상태가 some kind of weird cookie-based mechanism을 사용하여 추적되는) 동일한 요청을 보내고 서버가 쿼리를 완료 할 때까지 로컬 데이터베이스에 레코드를 누적하는 루프를 작성해야했습니다.

다음은 주어진 data.frame을 기반으로 빈 테이블을 생성하기 위해 SQL을 수동으로 생성 한 다음, 매개 변수화 된 배치 크기를 사용하여 data.frame의 내용을 테이블에 삽입하는 코드입니다. 대부분은 paste()을 호출하여 SQL 문자열을 만들고, dbSendQuery()을 사용하여 실제 쿼리를 전송합니다. 또한 테이블 생성을 위해 postgresqlDataType()을 사용합니다. 난 항상 같은 열을 포함하는 것 (그리고 그것을 방지의 수단을 제공하지 않는 것) dbWriteTable() 달리, 데이터베이스 테이블에 row.names 열을 붙이는 귀찮게하지 않았다

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

참고.

관련 문제