これは私がそれを書く方法です。 sqldfは、nseではなく、より自然に文字列を処理します。したがって、ソースを使用するdata.frameの文字列/名前を渡してください。
library(sqldf); requireNamespace("checkmate")
db1 <- data.frame(a = c(1,2,3), d = c("a","b","c"), stringsAsFactors = F)
extract <- function(table_name, criteria_d) {
checkmate::assert_character(table_name, min.chars=1, len=1, any.missing=F)
checkmate::assert_character(criteria_d, min.chars=1, len=1, any.missing=F)
# Half-way attempt to prevent sql-injection. Values would need to be only numbers, letters, and underscores.
checkmate::assert_character(table_name, pattern="^\\w+$", len=1, any.missing=F)
checkmate::assert_character(criteria_d, pattern="^\\w+$", len=1, any.missing=F)
sql <- paste0("select * from [", table_name , "] where d ='", criteria_d, "'")
cat("Executing: `", sql, "`\n", sep="")
sqldf(sql, verbose=F)
}
extract("db1", "b")
何らかの理由で変数の文字列/名前がわからない場合は、extract(quote(db1), "b")
と同じです。
いくつかのメモ。
- 変数の名前を「d」に変更してより明確にしました。
- 私は
db2
とdb
があなたのシナリオに関連しないと仮定しました。
- あなたのコードをあまり変更しないようにしました。この機能が実際のデータベースに接続されている場合は、sql injectionから保護してください。
- sqlが少し複雑になる場合は、
glue::glue_sql()
を使用することを検討してください。応じて
編集@ Sayakさんのコメント:
data.frame 名
c("db1", "db2") %>%
purrr::map_df(extract, "b")
のベクトルをループに使用purrr::map_df()
とに結果を結合します単一のデータフレーム:
Executing: `select * from [db1] where d ='b'`
Executing: `select * from [db2] where d ='b'`
a d
1 2 b
2 1 b
これは、後でdplyr::bind_rows()
を呼び出す必要がないので、かなり滑らかです。
あなたが(それは常に「B」ではありませんので、 IE)の基準を変更する必要がある場合は、その列があなたのextract()
関数のパラメータを一致data.frame(としての入力をパッケージ化してpurrr::pmap_df()
を使用します。
ds_input <- tibble::tribble(
~table_name, ~criteria_d,
"db1", "b",
"db1", "c",
"db2", "c"
)
ds_input %>%
purrr::pmap_df(extract)
# Executing: `select * from [db1] where d ='b'`
# Executing: `select * from [db1] where d ='c'`
# Executing: `select * from [db2] where d ='c'`
# a d
# 1 2 b
# 2 3 c
# 3 3 c
SQL式が正しく構成されていません。この行を使ってみるとよいでしょう: 'Example = paste0(" select * from "、" x "、where b = '"、 "b"、 "'"、collapse = "") '。関数の内部部品をテストして、期待される出力が得られることを確認してください。 – lmo