问题
I have a variable in R that I would like to pass to a database. I could use paste
like many suggest when reading Google results, but that is unsafe because of SQL injection vulnerabilities. I\'d rather prefer something like this:
x <- 42
sqlQuery(db, \'SELECT Id, Name FROM People WHERE Age > ?;\', bind=c(x))
Is it possible to use parameterized queries with RODBC? If not, is there an alternative library that supports them?
I\'m using SQL Server, RODBC 1.3-6 and R 3.0.0.
回答1:
Mateusz Zoltak wrote RODBCext
package in 2014 (based on work by Brian Ripley and Michael Lapsley):
conn = odbcConnect('MyDataSource')
sqlPrepare(conn, "SELECT * FROM myTable WHERE column = ?")
sqlExecute(conn, 'myValue')
sqlFetchMore(conn)
Source: http://cran.r-project.org/web/packages/RODBCext/vignettes/Parameterized_SQL_queries.html
回答2:
These are the options that I know of using RODBC. I know that RSQLite supports parameter binding natively, but that is usually not an option for most people.
# Note that sprintf doesn't quote character values. The quotes need
# to be already in the sql, or you have to add them yourself to the
# parameter using paste().
q <- "select * from table where val1 = '%s' and val2 < %d and val3 >= %f"
sprintf(q,"Hey!",10,3.141)
# The gsub route means you can't easily use a single placeholder
# value.
q <- "select * from table where val1 = '?' and val2 < ? and val3 >= ?"
gsub("?","Value!",q,fixed = TRUE)
I deal with lots of canned queries for my work that require various
parameters. Since in my case I only have SELECT
privileges, and I'm the
only person running my code, I dont really need to worry about validation.
So I have basically gone the gsub
route, in order to be able to store all
my queries in separate .sql files. This is because the queries are often long
enough that keeping them in my .R files just gets unwieldy. Keeping them separate
makes it easier for me to edit and maintain them with formatting and highlighting that
is more SQL appropriate.
So I have written some small functions that read a query from a .sql file
and bind any parameters. I write the query with parameters denoted with colons,
i.e. :param1:
, :param2:
.
Then I use this function to read the .sql file:
function (path, args = NULL)
{
stopifnot(file.exists(path))
if (length(args) > 0) {
stopifnot(all(names(args) != ""))
sql <- readChar(path, nchar = file.info(path)$size)
p <- paste0(":", names(args), ":")
sql <- gsub_all(pattern = p, replacement = args, x = sql)
return(sql)
} else {
sql <- readChar(path, nchar = file.info(path)$size)
return(sql)
}
}
where gsub_all
is basically just a wrapper for a for loop over the
parameters and args
is a named list of parameter values.
That's the range of options that I'm aware of.
来源:https://stackoverflow.com/questions/16178640/parameterized-queries-with-rodbc