dplyr ::如果uid不存在,则追加到postgresql远程源

时间:2018-09-02 23:49:19

标签: r dplyr rpostgresql

除非我丢失了某些内容,否则文档中没有关于如何在实践中使用诸如db_write_table之类的功能的参考。软件包文档中唯一的参考是。

db_write_table(con, table, types, values, temporary = FALSE, ...)

types没有解释。 dplyr的远程连接功能似乎都没有在任何地方(例如, dplyr.tidyverse.org

我有一个数据库mydb和表mydata我可以连接

require(RPostgreSQL)
require(dplyr)

drv <- dbDriver("PostgreSQL")
sapply(dbListConnections(drv), dbDisconnect)
con <- dbConnect(drv, dbname = "mydb", host = "localhost", port = 5432, user = "username")
data_db = tbl(con, 'mydata')

远程数据tbl data_db包含带有一个称为uid的字段。我有一个data_frame dat,其中包含观察值,如果尚无mydata值,则需要附加到dat$uid上。

这是db_write_table可以完成的事情,还是需要SQL方法?

2 个答案:

答案 0 :(得分:1)

根据@hadley对此answer的评论,您可以使用dbWriteTable(append = TRUE)。这是一个使用SQLite的示例:

library(dplyr)

# Create some example data
con <- DBI::dbConnect(RSQLite::SQLite(), path = ":dbname:")
dd <- data.frame(uid = 1:20, value = LETTERS[1:20])
dat <- data.frame(uid = 15:26, value = LETTERS[15:26])
copy_to(con, dd, "my_data",
  temporary = FALSE, 
  indexes = list("uid", "value")
)

# Identify rows to append
dd_db <- tbl(con, "my_data")
dd_uid <- select(dd_db, uid) %>%
  collect() %>%
  unlist()
dat_to_append <- filter(dat, !(uid %in% dd_uid))

DBI::dbWriteTable(con, "my_data", dat_to_append, append = TRUE)

答案 1 :(得分:0)

因此,这是我的实现的价值,对于我的情况(对大数据库的小追加),该实现应该更好:

db_add_unmatched = function(con, remote, dat, uid, append = TRUE, row.names = FALSE){
  tbl_remote = tbl(con, remote)
  dat_matched = select(tbl_remote, uid) %>% filter(uid %in% dat[[uid]]) %>% collect
  if(nrow(dat_matched) == 0){
    dat_unmatched = dat
  } else dat_unmatched = anti_join(dat, dat_matched, by = uid)
  if(nrow(dat_unmatched) > 0){
    DBI::dbWriteTable(con, remote, dat_unmatched, append = append, row.names = row.names)
  } else message('No unmatched rows to add')
}

db_add_unmatched(con, 'mydata', dat, 'uid')