如何使用dbplyr动词组合来达到DBI::dbSendQuery(con, "DELETE FROM <table> WHERE <condition>")
的效果。
我想做的不是从数据库中查询数据,而是从表中删除或更新数据。
我希望能够用dplyr
的方式实现,但我不确定是否可能。我在包的参考文档中没有找到类似的内容。
dbplyr可以将dplyr命令翻译为查询数据库表的命令。我不知道是否有内置的方法可以使用纯dbplyr修改现有的数据库表。
这可能是一种设计选择。
这是我所有dbplyr工作的方法。通常使用自定义函数,该函数接受由dbplyr翻译产生的查询并将其插入到DBI调用中(您可以在我的dbplyr helpers GitHub存储库中看到此类示例)。
考虑这两种方法:(1)反连接(在所有列上)然后编写新表,(2)使用DELETE FROM
语法。
反连接方法的模拟
records_to_remove = remote_table %>%
filter(conditions)
desired_final_table = remote_table %>%
anti_join(records_to_remove, by = colnames(remote_table))
query = paste0("SELECT * INTO output_table FROM (",
sql_render(desired_final_table),
") AS subquery")
DBI::dbExecute(db_con, as.character(query))
DELETE FROM语法的模拟
records_to_remove = remote_table %>%
filter(conditions)
query = sql_render(records_to_remove) %>%
as.character() %>%
gsub(search_term = "SELECT *", replacement_term = "DELETE")
DBI::dbExecute(db_con, query)
filter
命令视为从表中删除行。例如,在 R 中,我们可能会运行:prepared_table = input_table %>%
filter(colX == 1) %>%
select(colA, colB, colZ)
可以将其视为在生成输出之前删除 colX == 1
的行:
output = prepared_table %>%
group_by(colA) %>%
summarise(sumZ = sum(colZ))
SELECT colA, SUM(colZ) AS sumZ
FROM (
SELECT colA, colB, colZ
FROM input_table
WHERE colX = 1
) AS prepared_table
GROUP BY colA
dbDeleteCustom = function(x, con, schema_name, table_name) {
#x: 1-row dataframe that contains 1 row for deletion
if (nrow(x) != 1) stop("Input dataframe must be exactly 1 row")
where_str <- purrr::map_chr(colnames(x), ~glue::glue_sql("{`.x`} = {x[[.x]]}", .con = con))
where_str <- paste(where_str, collapse = " AND ")
update_str <- glue::glue("DELETE FROM {schema_name}.{table_name} WHERE {where_str}")
# Execute ------------------------------------------------------------------
query_res <- DBI::dbSendQuery(con, update_str)
rowsAffected <- dbGetRowsAffected(query_res)
DBI::dbClearResult(query_res)
return (rowsAffected)
}
tryCatch(
pool::poolWithTransaction(con, function(conn) {
rowsAffected <- dbDeleteCustom(record_to_remove, conn, schema, "tableName ")
log_step(paste0("removed entries for action, rows affected: ", rowsAffected))
}
),
error = function(e){
"handle error - code"
}
)
dplyr
不同,dplyr
中的处理逻辑可以通过管道清晰地分离。但我不明白这与从表中删除行有什么关系。您的实际观点是什么?您能用另一种方式解释一下吗?谢谢。 - englealuze