![](/img/trans.png)
[英]How to Filter Several Dataframes Using Two Master Dataframes with Purrr's Pmap and Dplyr's Semi_Join
[英]How to specify overwrite = T in dplyr::semi_join() against Oracle
當我在 R 中進行一些分析時,我需要能夠執行 semi_join(),在其中獲取 Oracle 數據庫表中的所有值,其中本地 R tibble 中有匹配的行。
通常,我會這樣做:
con <- DBI::dbConnect(odbc::odbc(), "THEDATABASE")
db_tbl <- tbl(con, in_schema("OTHER_USER", "table_I_care_about")
local_tbl <- tibble(x = 1:5, y = 5:10)
new_tbl_from_db <- db_tbl %>%
semi_join(local_tbl, by = 'x', copy =T)
有時這有效。 但通常,我會收到此錯誤: Error: Table "dbplyr_001" exists in database, and both overwrite and append are FALSE
(當然,它並不總是 dbplyr_001——它可以是任何數字)。
如果我查看數據庫中的架構,我會發現存在一個名為dbplyr_001
的表,對此我並不感到驚訝。 我不介意 dbplyr 寫一些臨時表。 我試過手動將值插入到這個表中,這也很好用。
我不知道該怎么做是指定overwrite=TRUE
。 我試過將它作為進一步的參數傳遞給semi_join()
,但仍然得到相同的錯誤。 有沒有一種簡單的方法可以通過dplyr::semi_join()
傳遞overwrite=TRUE
或append=TRUE
?
雖然不是直接的解決方案,但其他三個選項是:
%in%
傳遞 ID 值下面每個的代碼。 請注意,我使用的是 SQL 服務器連接,因此某些數據庫語法可能會有所不同。 其中一些方法需要DBI
包,但dbplyr
可能正在使用它,因此您可能已經安裝了它。
這里的想法是創建一個文本字符串,其中包含將表刪除到數據庫中的命令。 然后使用來自DBI
包的dbExecute
在數據庫中執行此命令。
delete_table <- function(db_connection, db, schema, tbl_name){
# remove table if it exists
removal_query <- glue::glue("IF OBJECT_ID('{db}.{schema}.{tbl_name}', 'U') IS NOT NULL\n",
"DROP TABLE {db}{schema}.{tbl_name};")
result <- DBI::dbExecute(db_connection, as.character(removal_query))
DBI
包還包括將本地表直接寫入數據庫的功能。
copy_r_to_sql <- function(db_connection, db, schema, sql_table_name, r_table_name){
DBI::dbWriteTable(db_connection,
DBI::Id(catalog = db,
schema = schema,
table = sql_table_name),
r_table_name)
請注意,您需要 1.1.0 版或更高版本的 DBI 包。 以前的版本無法寫入用戶指定的架構。
如果本地表中只有少量 ID,則可以將它們作為%in%
子句的一部分傳遞。
id_list = local_table %>% select(x) %>% unlist()
new_tbl_from_db = db_tbl %>%
filter(x %in% id_list)
這會將所有 ID 放入遠程 WHERE 子句中。 如果您隨后調用show_query(new_tbl_from_db)
您應該會看到如下內容:
SELECT *
FROM db.schema.tbl
WHERE x IN (1, 2, 3, 4, 5, ....)
GitHub 上的其他 dbplyr 輔助函數
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.