R DBI ODBC错误:nanodbc / nanodbc.cpp:3110:07009:[Microsoft] [用于SQL Server的ODBC驱动程序13]无效的描述符索引

use*_*714 6 sql-server odbc r r-dbi nanodbc

我继续阅读的DBI/ODBC速度比快RODBC,因此我尝试如下:

require(DBI);require(odbc)
con <- DBI::dbConnect(odbc::odbc(), dsn = 'SQLSERVER1', database = 'AcumaticaDB')
Run Code Online (Sandbox Code Playgroud)

我可以成功连接到DSN,但执行以下查询:

rs <- dbGetQuery(con, "SELECT * FROM inventoryitem")
dbFetch(rs)
Run Code Online (Sandbox Code Playgroud)

给我以下错误:

result_fetch(res @ ptr,n,...)中的错误:nanodbc / nanodbc.cpp:3110:07009:[Microsoft] [用于SQL Server的ODBC驱动程序13]无效的描述符索引

我究竟做错了什么 ?请,没有RODBC解决方案。谢谢!

al-*_*ien 12

我也一直在为这个问题苦苦挣扎了几个月。但是,我遇到了一个也可以帮助您的解决方案。

简而言之,当某些文本列没有出现在整数/数字列之后时,就会出现问题。如果查询中的列未正确对齐,invalid index则会引发错误并且您的连接可能会冻结。那么问题是,我怎么知道在查询的末尾放什么?

要确定这一点,通常可以使用class()或来检查列typeof()。要检查数据库中的此类信息,您可以使用以下查询:

dbColumnInfo(dbSendQuery(con, "SELECT * from schema.table")) # You may not require the schema part...
Run Code Online (Sandbox Code Playgroud)

这将为感兴趣的数据集中的每一列返回一个带有类型字段的表。然后,您可以使用此表作为索引来对select()语句进行排序。我特别困难的是type表格中的字段都是数字!但是,我注意到每个带有负数的列放在 select 语句的末尾时,修复了我的查询,我可以很好地拉出整个表。例如,我的完整解决方案

# Create my index of column types (ref to the current order)
index <- dbColumnInfo(dbSendQuery(con, "SELECT * from schema.table"))
index$type <- as.integer(index$type) # B/c they are + and - numbers!

# Create the ref to the table
mySQLTbl <- tbl(con, in_schema("schema", "tablename"))

# Use the select statement to put all the + numbered columns first!
mySQLTbl %>%
  select(c(which(index$type>=0),
                 which(index$type<0)))
Run Code Online (Sandbox Code Playgroud)

至于发生这种情况的原因,我不确定,我没有数据访问权限来深入挖掘我的用例


小智 7

我很感激这个问题很久以前就被问到了,但我已经设法找到了解决方法。上面的答案让我大部分时间都在那里。我遇到的问题是 nvarchar 类型的列在 -1 的架构表中具有 CHARACTER_MAXIMUM_LENGTH,我理解这意味着它们是可能的最大长度。

我的解决方案是在 INFORMATION_SCHEMA.COLUMNS 表中查找相关表,然后适当地重新排列我的字段:

require(DBI);require(odbc)
library(tidyverse)
con <- DBI::dbConnect(odbc::odbc(), dsn = 'SQLSERVER1', database = 'AcumaticaDB')

column.types <- dbGetQuery(con, "SELECT COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='inventoryitem'")

ct <- column.types %>%
  mutate(cml = case_when(
    is.na(CHARACTER_MAXIMUM_LENGTH) ~ 10,
    CHARACTER_MAXIMUM_LENGTH == -1 ~ 100000,
    TRUE ~ as.double(CHARACTER_MAXIMUM_LENGTH)
    )
  ) %>%
  arrange(cml) %>%
  pull(COLUMN_NAME)

fields <- paste(ct, collapse=", ")
query <- paste("SELECT", fields, "FROM inventoryitems")

tbl(con, sql(query)) %>% head(5)
Run Code Online (Sandbox Code Playgroud)

  • 这效果很好。先生,您是凡人中的神。谢谢你! (2认同)

mlo*_*kot 5

rs <- dbGetQuery(con, "SELECT * FROM inventoryitem")
dbFetch(rs)
Run Code Online (Sandbox Code Playgroud)

如果inventoryitem表包含长数据/可变长度列(如混用VARBINARYVARCHAR)和简单类型的列(如INT),您无法查询他们通过ODBC任意顺序。

应用程序应确保将长数据列放在选择列表的末尾。

使用ODBC API调用从数据库中检索长数据SQLGetData,并且必须在获取该行中的其他数据之后才检索长数据。

这些是已知且已记录的ODBC限制

要从列中检索长数据,应用程序首先调用SQLFetchScroll或SQLFetch移至行并获取绑定列的数据。然后,应用程序调用SQLGetData。

请参阅https://docs.microsoft.com/zh-cn/sql/odbc/reference/develop-app/getting-long-data

  • 好的,这是一个神话(我深信不疑),“ S”是针对*结构化*而非*标准*的,但这并没有改变(在我看来)我的保留意见是关于需要了解有关表存储的详细信息/结构体。 (2认同)

mzu*_*uba 5

有一个解决方法:

重新排序您的SELECT语句,以便将较长的数据类型(通常是字符串)放在最后。

如果您有一个dbplyr自己生成的复杂查询,那么直接通过show_query(). 复制粘贴并修改第一条SELECT语句,使长数据类型排在列表的最后。然后它应该工作。

编辑:在许多情况下,可以通过将其添加到查询中来重新排序字段:

%>% select(var1, var2, textvar1, textvar2)
Run Code Online (Sandbox Code Playgroud)