基于行ID将值从R写入PostgreSQL表

基于行ID将值从R写入PostgreSQL表,r,postgresql,dataframe,lookup,R,Postgresql,Dataframe,Lookup,我在本地服务器上有一个PostgreSQL表分数,如下所示: ID Score_X Score_Y 1 NA NA 2 NA NA 3 NA NA 4 NA NA ID Score_X Score_Y 1 0.53 0.81 4 0.75 0.95 ID Score_X Score_Y 1 0.53 0.8

我在本地服务器上有一个PostgreSQL表
分数
,如下所示:

ID   Score_X   Score_Y
1       NA        NA
2       NA        NA
3       NA        NA
4       NA        NA
ID   Score_X   Score_Y
1      0.53      0.81
4      0.75      0.95
ID   Score_X   Score_Y
1      0.53      0.81
2       NA        NA
3       NA        NA
4      0.75      0.95
我在R中进行了一系列计算,生成了一个数据帧
Calc_分数
,如下所示:

ID   Score_X   Score_Y
1       NA        NA
2       NA        NA
3       NA        NA
4       NA        NA
ID   Score_X   Score_Y
1      0.53      0.81
4      0.75      0.95
ID   Score_X   Score_Y
1      0.53      0.81
2       NA        NA
3       NA        NA
4      0.75      0.95
我想将与R中每个ID对应的分数写入PostgreSQL表,这样最终的PostgreSQL表应该如下所示:

ID   Score_X   Score_Y
1       NA        NA
2       NA        NA
3       NA        NA
4       NA        NA
ID   Score_X   Score_Y
1      0.53      0.81
4      0.75      0.95
ID   Score_X   Score_Y
1      0.53      0.81
2       NA        NA
3       NA        NA
4      0.75      0.95
我有一个到PostgreSQL表的连接,名为
connection
,我使用函数
dbConnect()
设置该表。实际的桌子相当大。我可以使用R中的哪一行/代码将这些分数写入PostgreSQL表?我一直在寻找一个类似的问题,但什么也找不到。我试过了

dbWriteTable(connection, "Scores", value = Calc_Scores, overwrite=T, append = F, row.names = F)
但是,整个表将被覆盖。我只想更新分数


谢谢。

实现这一点的一种方法依赖于SQL的“更新”,本质上你是这样做的

- open a connection to your database
- loop over your changeset and for each row
    - form the update statement, i.e. for example via
      cmd <- paste('update table set x=', Score_x, ', y=', 
                   Score_y, ' where id=', id)
    - submit the cmd via eg `dbSendQuery`
- close the connection
-打开与数据库的连接
-循环您的变更集,并针对每一行
-形成更新语句,例如,通过

cmd可以选择创建临时表:

# Create temporary table
dbWriteTable(connection, "ScoresTmp", value = Calc_Scores, overwrite=T, append = F, row.names = F)

# Update main table
dbExecute(connection,"
UPDATE Scores
SET Score_X = ScoresTmp.Score_X,
    Score_Y = ScoresTmp.Score_Y
FROM ScoresTmp 
WHERE Scores.ID = ScoresTmp.ID
")

# Clean up
dbExecute(connection,"DROP TABLE ScoresTmp")
请注意,您应该能够使用
temporary=TRUE
选项创建真正的临时表:根据下面的@Sirius注释,它应该可以在
PostGreSQL
数据库上工作。
对于
SQLServer
数据库的用户,此选项不起作用,但他们可以使用
#
前缀创建临时表。
在上述示例中,这将是:

 dbWriteTable(connection, "#ScoresTmp", value = Calc_Scores, overwrite=T, append = F, row.names = F)

谢谢,但这不是我想要的。虽然它可以工作,但需要很长时间,因为我的实际数据库有大约200万个条目,必须对每个条目执行更新查询。寻找一个更快的方法。好吧,“仅仅许愿并不能让它变得如此”。这里没有“部分写入表”——SQL后端通常有大容量插入器,这与
dbWriteTable
类似,唯一的选择是删除表并编写更新。那会更快吗?这是“更安全”还是更好?不允许删除表然后写入更新。更新是为一家公司,我不想篡改他们的数据库。我可以访问他们的数据库,只允许对这些分数列进行更新。谢谢您的帮助。您可以将值上载到单独的表中,并让下游查询通过联接和合并使用这两个表。所以你根本就不会弄乱他们的数据。为什么不添加
temporary=TRUE
?这对客户的数据库更好,意味着不会有任何竞争issues@Sirius,感谢您的反馈:这正是我在我比较熟悉的
SQL Server
DB上所推荐的,但我不能确定它是否适用于
PostgreSQL
。也许@Ruan可以测试并确认它是正确的OK@Ruan,了解
temporary=T
是否在
PostGreSQL
中工作会很有趣。对于
SQLServer
临时表,只需使用
#
前缀,而不需要AFAIK不起作用的
temporary=T
,请参见。老实说,这是一个非常简单的谷歌搜索。临时表是一个已经确立的概念,实际上不需要熟悉。当然,请先试试,但每次谷歌搜索只需增加3行文本,就可以确认它们的工作原理。