2010-02-02 3 views
8

В пакете R's DBI я не нахожу средство для использования связанных переменных. Я нашел документ (оригинальная виньетка с 2002 года), в которой говорится о связанных переменных: «Возможно, DBI мог в какой-то момент в будущем реализовать эту функцию», но похоже, что до сих пор это осталось незавершенным.Связанные переменные в R DBI

Что люди в R используют для замены? Просто конкатенировать строки прямо в SQL? У этого есть некоторые очевидные проблемы для безопасности производительности &.

EDIT:

Вот пример того, как заполнители может работать:

query <- "SELECT numlegs FROM animals WHERE color=?" 
result <- dbGetQuery(caseinfo, query, bind="green") 

Это не очень хорошо продуманный интерфейс, но идея состоит в том, что вы можете использовать значение для bind и драйвер обрабатывает сведения об экранировании (если базовый API не обрабатывает связанные переменные изначально), если вызывающий абонент не должен переопределять его [плохо].

+0

Можете ли вы предоставить примерный код, который будет работать так, как вам бы хотелось, чтобы он работал? какое поведение вы ожидаете от связанных переменных? –

+0

Вы имеете в виду что-то вроде этого? http://stackoverflow.com/questions/2182337/how-to-use-a-variable-name-in-a-mysql-statement –

+1

Я чувствую запах нового DBI с лучшими функциями. Мы все будем счастливы бета-тестерами, Кен .... –

ответ

16

Для тех, кто придя к этому вопросу, как я только что сделал после googling для rsqlite и dbgetpreparedquery, кажется, что в последней версии rsqlite вы можете запустить запрос SELECT с переменными bind. Я просто побежал следующее:

query <- "SELECT probe_type,next_base,color_channel FROM probes WHERE probeid=?" 
probe.types.df <- dbGetPreparedQuery(con,que,bind.data=data.frame(probeids=ids)) 

Это было относительно быстро (выбор 2000 строк из таблицы в 450 000 строк) и невероятно полезно.

FYI.

+0

Я не понимаю, какая разница между dbgetpreparedquery и dbsendpreparedquery. – Carbon

+1

Как я понимаю, функции 'GetQuery' возвращают результаты в качестве фрейма данных, тогда как функции' SendQuery' возвращают курсор, из которого вы можете запрашивать результаты в партиях, используя ' fetch'. Ознакомьтесь с документацией для RSQLITE :: query http://cran.r-project.org/web/packages/RSQLite/RSQLite.pdf –

1

Эй, эй, - я только что обнаружил, что RSQLite, что это то, что я использую в этом случае, действительно привязал переменную поддержку:

http://cran.r-project.org/web/packages/RSQLite/NEWS

Смотрите запись о dbSendPreparedQuery() и dbGetPreparedQuery().

Таким образом, в теории, что превращает эту гадость:

df <- data.frame() 
for (x in data$guid) { 
    query <- paste("SELECT uuid, cites, score FROM mytab WHERE uuid='", 
       x, "'", sep="") 
    df <- rbind(df, dbGetQuery(con, query)) 
} 

в это:

df <- dbGetPreparedQuery(
    con, "SELECT uuid, cites, score FROM mytab WHERE uuid=:guid", data) 

К сожалению, когда я на самом деле попробовать это, кажется, что это только для INSERT заявлений и т.п., а не для SELECT заявлений, потому что я получаю ошибку: RS-DBI driver: (cannot have bound parameters on a SELECT statement).

Предоставление этой возможности было бы фантастическим.

Следующим шагом будет поднять это на сам DBI, чтобы все БД могли воспользоваться им и предоставить реализацию по умолчанию, которая просто вставляет его в строку, как мы все делаем сейчас.

3

Ниже приведено резюме того, что в настоящее время поддерживается в RSQLite для связанных параметров . Вы правы, что в настоящее время нет поддержки для SELECT, но для этого нет веской причины, и я хотел бы добавить поддержку .

Если вы чувствуете, как взлом, вы можете получить только для чтения, проверку всех связанных DBI пакетов здесь:

use --user=readonly --password=readonly 

https://hedgehog.fhcrc.org/compbio/r-dbi/trunk 
https://hedgehog.fhcrc.org/compbio/r-dbi/trunk/DBI 
https://hedgehog.fhcrc.org/compbio/r-dbi/trunk/SQLite/RSQLite 

Я хотел бы получать патчи, особенно если они включают в себя тесты и документацию. Унифицированный diff, пожалуйста.Я на самом деле все мои разработки с помощью Git и поэтому лучший случай, чтобы создать GIT клон сказать RSQLite, а затем отправить мне посмотреть различия в git format-patch -n git-svn..

Во всяком случае, вот несколько примеров:

library("RSQLite") 

make_data <- function(n) 
{ 
    alpha <- c(letters, as.character(0:9)) 
    make_key <- function(n) 
    { 
     paste(sample(alpha, n, replace = TRUE), collapse = "") 
    } 
    keys <- sapply(sample(1:5, replace=TRUE), function(x) make_key(x)) 
    counts <- sample(seq_len(1e4), n, replace = TRUE) 
    data.frame(key = keys, count = counts, stringsAsFactors = FALSE) 
} 

key_counts <- make_data(100) 


db <- dbConnect(SQLite(), dbname = ":memory:") 

sql <- " 
create table keys (key text, count integer) 
" 

dbGetQuery(db, sql) 

bulk_insert <- function(sql, key_counts) 
{ 
    dbBeginTransaction(db) 
    dbGetPreparedQuery(db, sql, bind.data = key_counts) 
    dbCommit(db) 
    dbGetQuery(db, "select count(*) from keys")[[1]] 
} 

## for all styles, you can have up to 999 parameters 

## anonymous 
sql <- "insert into keys values (?, ?)" 
bulk_insert(sql, key_counts) 


## named w/ :, $, @ 
## names are matched against column names of bind.data 

sql <- "insert into keys values (:key, :count)" 
bulk_insert(sql, key_counts[ , 2:1]) 

sql <- "insert into keys values ($key, $count)" 
bulk_insert(sql, key_counts) 

sql <- "insert into keys values (@key, @count)" 
bulk_insert(sql, key_counts) 

## indexed (NOT CURRENTLY SUPPORTED) 
## sql <- "insert into keys values (?1, ?2)" 
## bulk_insert(sql) 
Смежные вопросы