简体   繁体   English

R DBI参数化查询:服务器最多支持2100个参数

[英]R DBI Parametrized Query: The server supports a maximum of 2100 parameters

I am looking to an R solution to this problem.我正在寻找这个问题的 R 解决方案。 My list of parameters is over 18000 long, so I attempted to split this up into a for-loop to run the query during each iteration with 2000 parameters (except the last iteration, which may have less than 2000).我的参数列表超过 18000 个,因此我尝试将其拆分为一个 for 循环,以便在每次迭代期间使用 2000 个参数运行查询(最后一次迭代除外,它可能少于 2000 个)。 However, it seems to be "storing" parameters somewhere during each iteration, so after the first iteration it tells me I hit the limit.然而,它似乎在每次迭代期间“存储”参数,所以在第一次迭代之后它告诉我我达到了极限。 If I break it up into chunks of 1000, it breaks down after the second iteration.如果我把它分成 1000 个块,它会在第二次迭代后分解。 My code looks like:我的代码如下所示:

Start_List<-(some list of values)

for (i in 1:ceiling(length(List)/2000)) {

  #Partition List into chunks of length 2000
  List<-Start_List[2000*(i-1)+1:min(2000*i,length(Start_List))]
  
  #Create qmarks for List
  qmarks_List <- paste(rep("?",  length(List)), collapse = ",")
  
  #Query 
  
  
  query <- paste("
                SELECT columns
                FROM table
                WHERE column IN (", qmarks_List, ")

    ")
  
   loop_df <- dbGetQuery(db, query, params= c(as.list(List)))
  
#Store the query in a list
  query_list[[i]]<-loop_df
}

How can I clear the parameters so it starts back at 0 parameters each iteration?如何清除参数,使其每次迭代都从 0 参数开始?

While I cannot reproduce this bug, I can present an alternative: upload your value to a temporary table, query against it (either set-membership or left-join), then delete it.虽然我无法重现此错误,但我可以提出替代方案:将您的值上传到临时表,对其进行查询(设置成员资格或左联接),然后将其删除。 The reason to use bound-parameters in the first place is to prevent SQL injection (malicious or accidental corruption), and I believe this suggestion preserves that intent.首先使用绑定参数的原因是为了防止 SQL 注入(恶意或意外损坏),我相信这个建议保留了这种意图。

DBI::dbWriteTable(con, "#sometable", data.frame(val = Start_List), create = TRUE)

## choose one from:
DBI::dbGetQuery(con, "select Columns from table where column in (select val from #sometable)")
DBI::dbGetQuery(con, "select t2.Columns from #sometable t1 left join table t2 on t1.val=t2.column")

## cleanup, though the temp table will auto-delete when you disconnect
DBI::dbExecute(con, "drop table #sometable")

While this should fix the problem you're having, it also should simplify and speed-up your process: instead of iterating over groups of your 18K-long list, it does a single query, single data-pull, to retrieve all of the records.虽然这应该可以解决您遇到的问题,但它还应该简化和加快您的流程:它不是迭代 18K 长列表的组,而是执行单个查询、单个数据拉取,以检索所有记录。 If you still need them grouped afterwards, that can be done easily in R (perhaps more easily than in SQL, but I'm confident a SQL-guru could demonstrate a safe/fast/efficient SQL method for this as well).如果您之后仍然需要将它们分组,则可以在 R 中轻松完成(可能比在 SQL 中更容易,但我相信 SQL 专家也可以为此演示安全/快速/高效的 SQL 方法)。

If you aren't aware of temp tables in SQL Server: prepending with # makes it a per-connection temporary table, meaning that no other connected user (even same user, different connection) will see this table;如果您不知道 SQL Server 中的临时表:使用#前缀使其成为每个连接的临时表,这意味着没有其他连接的用户(即使是同一用户,不同的连接)将看到此表; prepending with ## makes it a "global" temporary table, meaning that the same user on any connection will see the table.使用##前缀使其成为“全局”临时表,这意味着任何连接上的同一用户都将看到该表。 Both types are automatically dropped when this connection closes.当此连接关闭时,这两种类型都会自动删除。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM