Параметризованные запросы с RODBC
У меня есть переменная в R, которую я хотел бы передать в базу данных. Я мог бы использовать paste
как многие предлагают при чтении результатов Google, но это небезопасно из-за уязвимостей SQL-инъекций. Я бы предпочел что-то вроде этого:
x <- 42
sqlQuery(db, 'SELECT Id, Name FROM People WHERE Age > ?;', bind=c(x))
Можно ли использовать параметризованные запросы с RODBC? Если нет, есть ли альтернативная библиотека, которая их поддерживает?
Я использую SQL Server, RODBC 1.3-6 и R 3.0.0.
2 ответа
Матеуш Золтак написал RODBCext
пакет 2014 года (по материалам работ Брайана Рипли и Майкла Лапсли):
conn = odbcConnect('MyDataSource')
sqlPrepare(conn, "SELECT * FROM myTable WHERE column = ?")
sqlExecute(conn, 'myValue')
sqlFetchMore(conn)
Источник: http://cran.r-project.org/web/packages/RODBCext/vignettes/Parameterized_SQL_queries.html
Это те варианты, которые я знаю об использовании RODBC. Я знаю, что RSQLite изначально поддерживает привязку параметров, но обычно это не подходит для большинства людей.
# 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)
Я имею дело с большим количеством стандартных запросов для моей работы, которые требуют различных параметров. Так как в моем случае у меня есть только SELECT
привилегии, и я единственный, кто запускает мой код, мне не нужно беспокоиться о проверке.
Так что я в основном пошел gsub
маршрут, чтобы иметь возможность хранить все мои запросы в отдельных файлах.sql. Это потому, что запросы часто бывают достаточно длинными, поэтому их хранение в моих файлах.R становится громоздким. Разделяя их, мне легче редактировать и поддерживать их с форматированием и выделением, которые больше подходят для SQL.
Поэтому я написал несколько небольших функций, которые читают запрос из файла.sql и связывают любые параметры. Я пишу запрос с параметрами, обозначенными двоеточиями, т.е. :param1:
, :param2:
,
Затем я использую эту функцию для чтения файла.sql:
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)
}
}
где gsub_all
в основном это просто оболочка для цикла по параметрам и args
это именованный список значений параметров.
Это диапазон вариантов, которые я знаю.