2013-04-23 3 views
9

У меня есть переменная в R, которую я хотел бы передать в базу данных. I может использовать paste, как многие предлагают при чтении результатов Google, но это небезопасно из-за уязвимостей SQL-инъекций. Я бы предпочел что-то вроде этого:Параметрированные запросы с RODBC

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.

+0

Не то, что я знаю. 'sprintf' является единственным другим вариантом для« вставки », который я знаю, но это тоже не делает никакой санировки. – joran

+0

Как упоминается [здесь] (http://stackoverflow.com/a/1645086/142019) как «заполнители», но я все еще не мог найти, как их использовать. – 2013-04-23 20:46:08

+1

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

ответ

5

Это опции, которые я знаю об использовании 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-файла и связывают любые параметры. Я пишу запрос с параметрами, обозначенными двоеточиями, i.e. :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 является именованным списком значений параметров.

Это диапазон опций, о которых я знаю.

+1

Передача параметров запросу - это полная противоположность построению строки со строковыми манипуляциями ,Это опасно (допускает атаки SQL-инъекций), хрупкие (прерывания из-за проблем с локализацией при форматировании значений в строку) и медленные –

+0

@PanagiotisKanavos. Самое распространенное использование RODBC из R - для аналитиков данных для извлечения данных из db. Это несколько изменилось с появлением таких вещей, как Shiny, но большинство пользователей только подают запросы, которые они написали, в небольших количествах. Поэтому ни одна из этих проблем, вероятно, не будет беспокоить многих пользователей RODBC. – joran

+0

Наоборот, они * делают * затрагивают людей, которые пытаются передать, например, параметр даты, или забывают использовать правильный синтаксис для передачи строк Unicode и ANSI или сталкиваются с конфликтами сортировки. Аналитики данных гораздо чаще допускают такие ошибки. В любом случае ОП задал вопрос о том, как использовать * параметризованные запросы *, а не как построить строку SQL –

9

Матеуш Zoltak написал 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

+1

Да - это лучшее решение. Правильная параметризация уменьшает проблемы безопасности (SQL Injection) и может повысить производительность из-за кэшированных планов запросов (важно только, если запрос выполняется много). В качестве лучшего шаблона Craftsman для программного обеспечения я рекомендую такое решение. – ripvlan

Смежные вопросы