Sql server R RODBEXT和语句中的参数化?

Sql server R RODBEXT和语句中的参数化?,sql-server,r,rodbc,Sql Server,R,Rodbc,我一直在努力参数化一条SQL语句,该语句在WHERE子句中使用IN语句。我使用RodbText库进行参数化,但它似乎缺少列表的扩展 我希望能编写这样的代码 sqlExecute("SELECT * FROM table WHERE name IN (?)", c("paul","ringo","john", "george") 我正在使用以下代码,但不知道是否有更简单的方法 library(RODBC) library(RODBCext) # Search inputs names <

我一直在努力参数化一条SQL语句,该语句在WHERE子句中使用IN语句。我使用RodbText库进行参数化,但它似乎缺少列表的扩展

我希望能编写这样的代码

sqlExecute("SELECT * FROM table WHERE name IN (?)", c("paul","ringo","john", "george")
我正在使用以下代码,但不知道是否有更简单的方法

library(RODBC)
library(RODBCext)

# Search inputs
names <- c("paul", "ringo", "john", "george")

# Build SQL statement
qmarks <- replicate(length(names), "?")
stringmarks <- paste(qmarks, collapse = ",")
sql <- paste("SELECT * FROM tableA WHERE name IN (", stringmarks, ")")
# expand to Columns - seems to be the magic step required
bindnames <- rbind(names)

# Execute SQL statement
dbhandle <- RODBC::odbcDriverConnect(connectionString)
result <- RODBCext::sqlExecute(dbhandle, sql, bindnames, fetch = TRUE)
RODBC::odbcClose(dbhandle)
库(RODBC)
图书馆(RODBEXT)
#搜索输入

名称由于查询中唯一的参数是在
中的
集合中,因此可以不使用

sqlExecute(dbhandle,
    "SELECT * FROM table WHERE name IN (?)", 
    list(c("paul","ringo","john", "george")),
    fetch = TRUE)

sqlExecute
将列表中的值绑定到问号。在这里,它实际上会重复查询四次,对向量中的每个值重复一次。这样做似乎有点傻,但在尝试传递字符串时,让绑定负责设置适当的报价结构,而不是尝试将其粘贴到自己的文件中,在许多方面会更安全。通过这种方式,您将生成更少的错误,并避免许多数据库安全问题。

如果在字符对象中声明一个变量表,然后与查询连接,该怎么办

library(RODBC)
library(RODBCext)

# Search inputs
names <- c("paul", "ringo", "john", "george")

# Build SQL statement
sql_top <- paste0( "SET NOCOUNT ON \r\n DECLARE @LST_NAMES TABLE (ID NVARCHAR(20)) \r\n INSERT INTO @LST_NAMES VALUES ('", paste(names, collapse = "'), ('" ) , "')")

sql_body <- paste("SELECT * FROM tableA WHERE name IN (SELECT id FROM @LST_NAMES)")
sql <- paste0(sql_top, "\r\n", sql_body)

# Execute SQL statement
dbhandle <- RODBC::odbcDriverConnect(connectionString)
result <- RODBCext::sqlExecute(dbhandle, sql, bindnames, fetch = TRUE)
RODBC::odbcClose(dbhandle)

在PHP中,我看到了许多将变量直接放入sql语句的代码。那么,如果成功了,你为什么要在意呢?并非所有的事情都能在R中轻松完成。这是我第一次看到R连接到数据库。连接到数据库是R的主要功能之一。我将尝试一下。使用c()时,返回一个关于未使用的“cond”的错误,并且只使用了第一个值。。。但也许list()就是魔法。我在github上找到了代码,没有看到任何明显的东西。在我的例子中,执行4条语句可能没问题。严格来说,
sqkExecute
需要一个数据帧。列表恰好很容易转换为数据帧。而且,您不会注意到它会发出四个呼叫
sqlExecute
在数据帧的行上循环,为每行提取一个数据帧,并在最后将它们绑定在一起。从R端来看,不管SQL端发生了什么,它都像是一个调用。是的,谢谢。当我重新创建我的样本时,这是一个输入错误。我正在使用data.frame。。。data.frame(names=c(“john”,…)当然不起作用。嗨@Benjamin-很抱歉耽搁了,真的有工作要做。谢谢你的帮助和使用列表的提示()。我使用了您的示例,发现它确实发出了多个查询!但是,该实现使用游标来完成任务,并且总体cpu/读取/持续时间比在SQL中发出本机IN语句要长。在我的特定情况下,数据子集的开销非常大(980 vs 296 ms和5200 vs 126读取)。随着我的全套数据的增长,我担心可伸缩性。不过,谢谢你-了解了一些关于我不知道的库的知识。谢谢你的想法。但是用值简单地输出IN子句更容易。temp表不会为小列表购买任何东西,而是会跨线添加要编译的文本。我想避免sqlinjection发出并获取已编译的可重用查询计划。生成临时表代码会导致生成不同的查询,因此该计划无法重用。
SET NOCOUNT ON 
DECLARE @LST_NAMES TABLE (ID NVARCHAR(20)) 
INSERT INTO @LST_NAMES VALUES ('paul'), ('ringo'), ('john'), ('george')
SELECT * FROM tableA WHERE name IN (SELECT id FROM @LST_NAMES)