我似乎无法在任何地方找到这个问题的答案。我正在使用 read.csv 函数将 csv 读取到数据框中。然后我使用 dbWriteTable 将数据帧内容写入 mysql 表。这对于创建表的初始运行非常有用,但在此之后的每次运行都需要根据表中是否已存在记录来执行插入或更新。
数据框中的第一列是主键,其他记录包含的数据可能会在每次提取 csv 的新副本时发生更改。每次我提取 CSV 时,如果主键已经存在,我希望它用新数据更新该记录,如果主键不存在(例如:自上次运行以来的新键),我希望它只需将记录插入表中即可。
这是我当前的 dbWriteTable。这会在第一次运行时很好地创建表,并且还在表中插入一个“时间戳”列,该列设置为“更新时 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)
现在,下次运行此命令时,我只是希望它更新表中已有的所有主键,并添加任何新主键。我也不希望在主键从 CSV 源中消失时丢失任何记录。
是否可以使用 dbWriteTable 或其他 R 函数进行此类更新?
如果这是不可能的,是否可以只运行一个 mysql 查询来删除任何重复的 PrimaryKey 记录并仅保留具有最新时间戳的 1 条记录?因此,我将运行 dbWriteTable 来追加新数据,然后运行 MySQL 查询来删除旧记录。
显然,我无法将第一列定义为数据库中的实际主键,因为我的追加/删除解决方案由于重复的键而无法工作,这很好,我总是可以向表中添加自动增量整数列如果需要的话,获取“真正的”主键。
想法?
最佳答案
考虑使用临时表(最终表的精确副本,但记录较少),然后对最终表运行 INSERT
和 UPDATE
查询,这将处理这两种情况没有重叠(加上主键是约束,如果尝试复制任何内容,查询将出错):
- 如果不存在则追加记录 - 使用LEFT JOIN NULL查询
- 要更新的记录(如果存在)。 - 使用UPDATE INNER JOIN查询
对于前者,SQL 编码人员经常争论是否 LEFT JOIN NULL or NOT IN or NOT EXISTS是最佳解决方案,当然“取决于”。这里使用的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 中处理。
关于mysql - r - dbWriteTable 或 MySQL 删除查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33860738/