У вас есть SQL-инъекция, а не параметризованный запрос. Вы можете взглянуть на пакет RODBCext
и его винье.
Чтобы правильно параметризовать запрос, вы можете сделать
library(RODBC)
library(RODBCext)
channel = odbcConnect("VerticaDB")
query = paste0("select * from Item_History ",
"where Item_Exp_Date between ? and ? ",
"and Item_Code = ?")
item <- c("A1", "A2", "B1", "B2")
x <- 3
y <- 10 # I don't actually know what your x and y are, but hopefully you get the idea
sqlExecute(
channel = channel,
query = query,
data = list(x = rep(x, length(item)),
y = rep(y, length(item)),
item = item),
fetch = TRUE,
stringsAsFactors = FALSE
)
Однако это имеет большой недостаток, поскольку sqlExecute
будет выполнять запрос для каждой строки в аргументе data
(список будет приведен к фрейму данных). Если у вас есть сотни элементов в вашем векторе item
, вы будете выполнять сотни запросов к вашему экземпляру SQL, что может быть не особенно эффективным.
Менее очевидный способ сделать это — написать хранимую процедуру для создания запроса.
Ваша хранимая процедура в SQL может выглядеть так
CREATE PROCEDURE schema.specialQuery
@x int;
@y int;
@in varchar(2000);
AS
BEGIN
DECLARE @query = varchar(8000);
SET @query = 'select * from Item_History ' +
'where Item_Exp_Date between ' + convert(@x, varchar(10)) +
' and ' + convert(@y, varchar(10)) +
' and Item_Code IN (' + @in ')'
EXEC @query
END
GO
Возможно, вам придется повозиться с функциями convert
и некоторыми кавычками, но это будет работать с
sqlExecute(
channel = channel,
query = "EXECUTE schema.specialQuery @x = ?, @y = ?, @in = ?",
data = list(x = x,
y = y,
in = sprintf("'%s'", paste0(item, collapse = "', '"))),
fetch = TRUE,
stringsAsFactors = FALSE
)
К сожалению, этот подход по-прежнему подвержен проблемам с плохо отформатированными символьными строками, передаваемыми через item
, но он, вероятно, быстрее, чем выполнение сотен запросов в первом показанном мной подходе.
person
Benjamin
schedule
24.08.2016