我似乎在任何地方都找不到答案。我正在使用read.csv函数将csv读取到数据帧中。然后,我使用dbWriteTable将数据帧内容写入mysql表。这对于创建表的初始运行非常有用,但是此后的每次运行都需要根据表中是否已存在记录进行插入或更新。
数据框中的第一列是主键,其他记录包含的数据可能会在我每次提取csv的新副本时更改。每次我拉CSV时,如果主键已经存在,我希望它用新数据更新该记录,并且如果主键不存在(例如:自上次运行以来的新键),我希望它只需将记录插入表中即可。
这是我当前的dbWriteTable。这会在第一次运行时创建该表,并且还会在表中插入“ Timestamp”列,该列设置为“ on update CURRENT_TIMESTAMP”,以便我知道每条记录的最后更新时间。
dbWriteTable(mydb, value=csvData, name=Table, row.names=FALSE, field.types=list(PrimaryKey="VARCHAR(10)",Column2="VARCHAR(255)",Column3="VARCHAR(255)",Timestamp="TIMESTAMP"), append=TRUE)
现在,下一次我运行此命令时,我只希望它更新表中已经存在的任何PrimaryKey,并添加任何新的PrimaryKey。我也不想丢失任何记录,以防PrimaryKey从CSV源消失。
是否可以使用dbWriteTable或其他R函数进行这种更新?
如果那是不可能的,是否有可能只运行一个mysql查询,该查询将删除任何重复的PrimaryKey记录,并仅保留具有最新时间戳的1条记录?因此,我将运行dbWriteTable追加新数据,然后运行MySQL查询以删减旧记录。
显然,我无法将第1列定义为数据库中的实际PrimaryKey,因为附加键会导致我的附加/删除解决方案无法正常工作,这很好,我始终可以在表中为“真正的”主键(如果需要)。
有什么想法吗?
考虑使用临时表(最终表的精确副本,但记录较少),然后运行INSERT
和UPDATE
查询最终表,这将处理两种情况而不会出现重叠(加上主键是约束,并且如果尝试进行重复,查询将出错)任何):
关于前者,是否使用LEFT JOIN NULL或NOT IN或NOT EXISTS是“取决于”的最佳解决方案,在SQL编码人员中经常有争论。此处使用的Left Join确实避免了子查询。但是,如果需要,请考虑这些途径。
# DELETE LAST SET OF TEMP DATA
dbSendQuery(mydb, "DELETE FROM tempTable")
# APPEND R DATA FRAME TO TEMP DATA
dbWriteTable(mydb, value=csvData, name=tempTable, row.names=FALSE,
field.types=list(PrimaryKey="VARCHAR(10)", Column2="VARCHAR(255)",
Column3="VARCHAR(255)", Timestamp="TIMESTAMP"),
append=TRUE, overwrite=FALSE)
# LEFT JOIN ... NULL QUERY TO APPEND NEW RECORDS NOT IN TABLE
dbSendQuery(mydb, "INSERT INTO finalTable (Column1, Column2, Column3, Timestamp)
SELECT Column1, Column2, Column3, Timestamp
FROM tempTable f
LEFT JOIN finalTable t
ON f.PrimaryKey = t.PrimaryKey
WHERE f.PrimaryKey IS NULL;")
# UPDATE INNER JOIN QUERY TO UPDATE MATCHING RECORDS
dbSendQuery(mydb, "UPDATE finalTable f
INNER JOIN tempTable t
ON f.PrimaryKey = t.PrimaryKey
SET f.Column1 = t.Column1,
f.Column2 = t.Column2,
f.Column3 = t.Column3,
f.Timestamp = t.Timestamp;")
在大多数情况下,如果您需要更改数据库,上述查询将在大多数SQL后端中符合要求。某些RDMS不支持,UPDATE INNER JOIN
但是可以使用等效的替代方法。最后,这条路线的美在于所有处理都在SQL引擎而不是R中处理。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句