postgresql R向SQL数据库中的现有表添加新数据框(UPSERT)

mfuanj7w  于 2023-03-22  发布在  PostgreSQL
关注(0)|答案(1)|浏览(113)

我在Postgres sql数据库中以表的形式存储了一个数据集,即df_old。现在我想添加新数据,即df_new,并使用它们更新现有表。所有数据都有一个唯一标识符(主键),请参见id列。如果id已存在于现有表中,则不应插入该值。否则,插入所有其他值。以下是我的示例代码,它创建了现有数据和新数据,并已将现有数据插入Postgres SQL数据库中:

library(tidyverse)
library(DBI)
library(RPostgres)
library(dbplyr)

# Create database connection
# You have to insert your own credentials for your own SQL database
con <- dbConnect(RPostgres::Postgres(), dbname = "mydatabase", ...)

# Create existing dataframe
df_old <- tribble(
  ~id, ~colA, ~colB, ~colC, ~colD,
  1, 23, 45, "Value g", 8,
  2, 67, 56, "Value h", 3,
  3, 26, 12, "Value w", 7,
  4, 98, 85, "Value h", 9
)

# Create existing table in database
dbWriteTable(con, "my_table", df_old, row.names = F)

# Create new dataframe
df_new <- tribble(
  ~id, ~colA, ~colB, ~colC, ~colD,
  2, 67, 56, "Value h", 3,
  5, 85, 56, "Value s", 5,
  6, 23, 16, "Value t", 2
)

现在我想把新值添加到已经存在的数据库表中,但是,我被一个命令卡住了,这个命令应该把新ID的值添加到数据库表中,而忽略现有ID的值。
下面是我想要的输出(更新了SQL数据库中的表“my_table”):
未插入df_new中id = 2的第一个值,因为df_old表中已存在此值。

desired_df <- tbl(con, "my_table") %>% collect()

desired_df

     id  colA  colB colC     colD
1     1    23    45 Value g     8
2     2    67    56 Value h     3
3     3    26    12 Value w     7
4     4    98    85 Value h     9
5     5    85    56 Value s     5
6     6    23    16 Value t     2

提前感谢!

eoxn13cs

eoxn13cs1#

经过长时间的搜索,我找到了upsert的方法。dbUpsert-包提供了必要的函数:

library(devtools)
install_github("timeddilation/dbUpsert")

library(dbUpsert)

dbUpsertTable(
  con,
  "my_table",
  df_new,
  "id")

# print the upserted table from the database
dbGetQuery(
  con,
  "SELECT * FROM my_table") %>% tibble()

     id  colA  colB colC     colD
1     1    23    45 Value g     8
2     2    67    56 Value h     3
3     3    26    12 Value w     7
4     4    98    85 Value h     9
5     5    85    56 Value s     5
6     6    23    16 Value t     2

但是,dbUpsert-包中的dbUpsertTable-函数也有限制。
首先,软件包要求R〉= 4.1.0。
如果新的 Dataframe 包含一些列的不同值,也没有关于是否应该更新现有值的选项。该函数只是用新值覆盖现有值。

相关问题