R,dbGetQuery()不会为参数中传递的所有值选择记录 [英] R, dbGetQuery() will not select records for all values passed in params

查看:68
本文介绍了R,dbGetQuery()不会为参数中传递的所有值选择记录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图获取dbGetQuery来从SybaseIQ表(test_in)中检索字符列表(test_ID2)中引用的所有行.结果是仅检索到test_ID2中的第一个条目.

I am trying to get dbGetQuery to retrieve all rows referenced in a char list (test_ID2) from a SybaseIQ table (test_in). The result is that only the first entry in test_ID2 is retrieved.

dbGetQuery()看起来像这样:

the dbGetQuery() looks like this:

test_con <- DBI::dbConnect(odbc::odbc(),
                           driver = 'SybaseIQ',
                           host = 'xxx.xx.xxx',
                           port = 'xxxx',
                           uid = 'xxxx',
                           pwd = 'xxxx')

test_out <- dbGetQuery(test_con,"SELECT * FROM test_in WHERE ID2 = ?", 
                           params = list(test_ID2))

test_in看起来像这样:

test_in looks like this:

> test_in
          ID1       DATE       ID2  QTY
115 18383M472 2017-02-01 93964W108  594
116 18383M472 2017-02-01 939653101  254
117 18383M472 2017-02-01 948741103  437
118 18383M472 2017-02-01 95040Q104 1236
119 25459W458 2017-02-01 G5876H105 4542
120 25459W458 2017-02-01 N07059210  557
121 25459W458 2017-02-01 N6596X109 1205
122 25459W458 2017-02-01 Y09827109 1401
123 25459W458 2017-02-01 007903107 8223
124 25459W458 2017-02-01 032654105 1609
125 25459W458 2017-02-01 038222105 3709

test_ID2看起来像这样:

test_ID2 looks like this:

> test_ID2
[1] "939653101" "N6596X109" "N99999999"

上述dbGetQuery()的结果仅包含一个条目

the result from the above dbGetQuery() contains only one entry

> test_out
          ID1       DATE       ID2 QTY
116 18383M472 2017-02-01 939653101 254

,它丢失了ID2 ="N6596X109"的条目.

and it misses the entry with ID2 = "N6596X109".

我做错什么了吗?

感谢您的想法!

更新

似乎有效的方法是使用 glue_sql()以及 dbSendQuery() dbFetch()

what seems to work is using glue_sql() along with dbSendQuery() and dbFetch()

test_ID2 <- as.character(test_ID2)

detail_qry <- glue_sql("select * from test_in where ID2 IN ({ID2*})",
                       ID2 = test_ID2, .con = test_con)

details <- dbSendQuery(test_con,detail_qry)

test_out <- dbFetch(details)

我仍然很好奇为什么以前的代码不起作用.似乎更直接.

I am still curious to understand why the previous code doesn't work. It seems to be more direct.

推荐答案

在SQL中,可以更有效地重用已准备好的语句.这样,使用绑定参数的预备语句可以受益,因此在需要重用查询时,使用无数据的预备语句可以利用此优势.(诚​​然,这里有些挥舞之手,坦白地说,...现在,我将提供它作为 glue_sql 的替代方法.)

In SQL, prepared statements can be reused more efficiently. With this, prepared statements that use bound parameters can benefit, so using a data-less prepared statement can take advantage of this when you need to reuse the query. (There is a little hand-waving going on here, admittedly ... for now, I'll just offer this as an alternative to glue_sql.)

从普通的SQL查询开始,演示了我们如何提供简单集合(使用 params = ).

Starting with a vanilla SQL query, a demonstration of how we want simple sets to be provided (using params=).

# con <- DBI::dbConnect(...)
DBI::dbGetQuery(con, "select 1 where 1 in (1,2)")
#    
# 1 1
DBI::dbGetQuery(con, "select 1 where 1 in (?,?)", params=list(1,2))
#    
# 1 1
DBI::dbGetQuery(con, "select 1 where 1 in (?,?)", params=list(2,3))
# [1] 
# <0 rows> (or 0-length row.names)

让我们稍微正式一点:

DBI::dbWriteTable(con, "testcars", mtcars)
cyls <- c(4, 6)
qry <- sprintf("select * from testcars where cyl in (%s)", paste(rep("?", length(cyls)), collapse = ","))
qry
# [1] "select * from testcars where cyl in (?,?)"

通常,R用户将只使用 DBI :: dbGetQuery 进行一次查询,并可以选择绑定参数.但是,如果您有详尽的查询和/或需要提高查询速度,则可以执行多个步骤.(我目前无法立即量化这种差异.)通常,这些步骤是:

Normally, R users will just use DBI::dbGetQuery for a one-shot query, optionally with bound parameters. However, you can do a multi-step if you have an elaborate query and/or need some improvement in query speed. (I cannot off-hand quantify this difference at the moment.) The steps are typically:

  1. 发送查询/声明;
  2. 可选地绑定参数;
  3. 获取数据;最后
  4. 关闭结果集.

res <- DBI::dbSendQuery(con, qry)
res
# <OdbcResult>
#   SQL  select * from testcars where cyl in (?,?)
#   ROWS Fetched: 0 [complete]
#        Changed: 0
res2 <- DBI::dbBind(res, list(2, 4))
DBI::dbFetch(res2)
#         row_names  mpg cyl  disp  hp drat    wt  qsec vs am gear carb
# 1      Datsun 710 22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
# 2       Merc 240D 24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2
# 3        Merc 230 22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2
# 4        Fiat 128 32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1
# 5     Honda Civic 30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2
# 6  Toyota Corolla 33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1
# 7   Toyota Corona 21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1
# 8       Fiat X1-9 27.3   4  79.0  66 4.08 1.935 18.90  1  1    4    1
# 9   Porsche 914-2 26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2
# 10   Lotus Europa 30.4   4  95.1 113 3.77 1.513 16.90  1  1    5    2
# 11     Volvo 142E 21.4   4 121.0 109 4.11 2.780 18.60  1  1    4    2

我们可以通过绑定新参数(无需新查询)来重用该查询(特别是 res ult集):

And we can reuse that query (that result set, specifically) with binding new parameters (without a new query):

res2 <- DBI::dbBind(res, list(6, 7))
DBI::dbFetch(res2)
#        row_names  mpg cyl  disp  hp drat    wt  qsec vs am gear carb
# 1      Mazda RX4 21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
# 2  Mazda RX4 Wag 21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
# 3 Hornet 4 Drive 21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
# 4        Valiant 18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1
# 5       Merc 280 19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4
# 6      Merc 280C 17.8   6 167.6 123 3.92 3.440 18.90  1  0    4    4
# 7   Ferrari Dino 19.7   6 145.0 175 3.62 2.770 15.50  0  1    5    6
DBI::dbClearResult(res2)

这篇关于R,dbGetQuery()不会为参数中传递的所有值选择记录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆