2010-02-02 25 views
8

Nel pacchetto DBI di R, non sto trovando una funzionalità per l'utilizzo di variabili associate. Ho trovato un documento (la vignetta originale del 2002) che parla di variabili vincolate, "Forse il DBI potrebbe ad un certo punto implementare questa funzionalità in futuro", ma sembra che finora non sia stato risolto.Variabili di binding in R DBI

Cosa usano le persone in R per un sostituto? Basta concatenare le stringhe direttamente nell'SQL? Questo ha alcuni problemi evidenti per la prestazione di sicurezza &.

EDIT:

Ecco un esempio di come segnaposto potrebbero funzionare:

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

Questo non è un'interfaccia molto ben congegnato, ma l'idea è che si può utilizzare un valore per bind e il driver gestisce i dettagli dell'escape (se l'API sottostante non gestisce le variabili vincolate in modo nativo) senza che il chiamante debba reimplementarlo [male].

+0

puoi fornire qualche esempio di codice che funzionerebbe come vorresti che funzionasse? quale comportamento ti aspetteresti che le variabili vincolate abbiano? –

+0

Intendi qualcosa del genere? http://stackoverflow.com/questions/2182337/how-to-use-a-variable-name-in-a-mysql-statement –

+1

Sento odore di un nuovo DBI con caratteristiche migliori in arrivo. Saremo tutti felici beta-tester, Ken .... –

risposta

16

Per chiunque arrivando a questa domanda come ho fatto dopo googling per rsqlite e dbgetpreparedquery, sembra che nell'ultima versione di rsqlite sia possibile eseguire una query SELECT con le variabili di bind. Ho appena eseguito il seguente:

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

Questa era relativamente veloce (selezionando 2000 righe di una tabella 450.000 riga) ed è incredibilmente utile.

FYI.

+0

Non sono chiaro quale sia la differenza tra dbgetpreparedquery e dbsendpreparedquery – Carbon

+1

Come ho capito, le funzioni 'GetQuery' restituiscono i risultati come un dataframe, mentre le funzioni' SendQuery' restituiscono un cursore dal quale è possibile richiedere i risultati in batch usando ' metodo di recupero Controlla la documentazione per RSQLITE :: query http://cran.r-project.org/web/packages/RSQLite/RSQLite.pdf –

1

Hey hey - Ho appena scoperto che RSQLite, che è quello che sto usando in questo caso, ha in effetti legata alla variabile di supporto:

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

vedere la voce su dbSendPreparedQuery() e dbGetPreparedQuery().

Quindi, in teoria, che trasforma questa cattiveria:

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)) 
} 

in questo:

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

Purtroppo, quando ho provato, sembra che è solo per INSERT dichiarazioni e simili, non per le dichiarazioni SELECT, perché viene visualizzato un messaggio di errore: RS-DBI driver: (cannot have bound parameters on a SELECT statement).

Fornire tale funzionalità sarebbe fantastico.

Il prossimo passo sarebbe quello di issare questo in DBI stesso in modo che tutti i DB possano trarne vantaggio e fornire un'implementazione predefinita che semplicemente lo incolli nella stringa come facciamo tutti noi stessi ora.

3

Di seguito è riportato un riepilogo di ciò che è attualmente supportato in RSQLite per i parametri associati. Hai ragione che al momento non è disponibile il supporto per SELECT, ma non c'è una buona ragione per questo e vorrei aggiungere il supporto per questo.

Se ti senti come l'hacking, è possibile ottenere una cassa di sola lettura di tutti le DBI relativi pacchetti qui:

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 

Mi piace ricevere patch, specialmente se includono test e documentazione. Diff Unified, per favore.Io in realtà faccio tutto il mio sviluppo utilizzando git e così migliore dei casi è quello di creare un clone git di dire RSQLite e poi mi inviare diff come git format-patch -n git-svn..

In ogni caso, ecco alcuni esempi:

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)