RODBC 和 Microsoft SQL Server:截断长字符串

2023-11-21

我正在尝试使用 R/RODBC 从 Microsoft SQL Server 数据库查询变量。 RODBC 正在将字符串截断为 8000 个字符。

原始代码:截断为 255 个字符(根据 ODBC 文档) library(RODBC) con_string <- odbcConnect("DSN") query_string <- "SELECT text_var FROM table_name" dat <- sqlQuery(con_string, query_string, stringsAsFactors=FALSE)

部分解决方案:修改查询字符串,在 7999 个字符后截断文本。 library(RODBC) con_string <- odbcConnect("DSN") query_string <- "SELECT [text_var]=CAST(text_var AS VARCHAR(8000)) FROM table_name" dat <- sqlQuery(con_string, query_string, stringsAsFactors=FALSE)

表/变量包含长达 250,000 个字符的文本字符串。我真的想在 R 中处理所有文本。这可能吗?

@BrianRipley 在以下文档的第 18 页讨论了该问题(但没有解决方案):https://cran.r-project.org/web/packages/RODBC/vignettes/RODBC.pdf

@nutterb 讨论了类似的问题RODBCextGitHub 上的包:https://github.com/zozlak/RODBCext/issues/6

在 SO 上看到过类似的讨论,但没有使用 VARCHAR>8000 的 RODBC 的解决方案。

RODBC sqlQuery() 在应该返回 varchar(MAX) 时返回 varchar(255)

RODBC 字符串被截断

Note:

  • R 3.3.2
  • 微软 SQL Server 2012
  • Linux RHEL 7.1
  • 用于 SQL Server 的 Microsoft ODBC 驱动程序

由于这是 Microsoft 提供的 ODBC 驱动程序的限制,因此在他们对驱动程序进行更改之前几乎没有什么可做的。 @zozlak 在您链接到的 GitHub 问题中解释了原因。

我倾向于在需要时使用存储过程来解决这个问题,但这通常需要为每个特定实例编写一个存储过程。在某些时候,我可能会想出一种更通用的方法来在存储过程中执行此操作,但我发现在存储过程中构造查询的过程非常乏味且令人沮丧。

因此,我只是花了一些时间构建一个函数,该函数将执行涉及 VARCHAR(MAX) 变量的有限查询。这是一种蛮力方法,对于 17000 个字符的变量,将其导出为三个变量并将它们粘贴到 R 中。它很粗糙,可能不是很有效,但这是我迄今为止想到的最佳解决方案。

另一个限制是它不允许您在查询中重命名变量。您将被数据库中命名的变量所困扰。如果您只涉及几个表,那可能不是问题。在非常复杂的数据库中,这可能会出现问题。但是,至少有了这个,您可以只查询 VARCHAR(MAX) 变量,其中包含一些必要的 ID,以便在 R 中执行合并。

正如 GitHub 问题中所讨论的,最好尽可能避免使用 VARCHAR(MAX)。如果确实需要未知长度,则 VARBINARY(MAX) 更容易查询。

Example

source("https://gist.githubusercontent.com/nutterb/d2e050dada608bb6213e61d0f8471b65/raw/be8717f318b3e3087e7c26c9a8f9d0a582a5daef/query_varchar_max"

channel <- odbcDriverConnect(...)

query_varchar_max(channel = channel,
                  id = c("idvar"),
                  varchar_max = c("varchar_max_var", "varchar_max_var2"),
                  from = "FROM dbo.table_name WHERE group = ?",
                  data = list(group = "A"))

功能码

#' @name query_varchar_max
#' @title Query a VARCHAR(MAX) Variable from SQL Server
#' 
#' @description The RODBC driver to SQL Server (SQL Server Native Client 11.0)
#'   reports the lenght of a VARCHAR(MAX) variable to be zero.  This presents 
#'   difficulties in extracting long text values from the database. Often, the
#'   ODBC will assume a length of 255 characters and truncate the text to that
#'   many characters.  The approach taken here searches the VARCHAR(MAX) variables 
#'   for the longest length, and extracts the data in segments to be pasted 
#'   together in R.  
#'   
#' @param channel A valid ODBC channel to a SQL Server database.
#' @param id A character vector of ID variables that may be used to merge the 
#'   data from this query into another dataset.
#' @param varchar_max a character vector of variable names that are to be 
#'   treated as if they are VARCHAR(MAX) variables. 
#' @param from A single character string providing the remainder of the query 
#'   to be run, beginning with the \code{FROM} statement.
#' @param stringsAsFactors \code{logical(1)}. Should character strings returned 
#'   from the database be converted to factors?
#' @param ... Additional arguments to \code{sqlExecute} when running the full 
#'   query.
#'   
#' @details \code{query_varchar_max} operates by determining how many columns of up to
#'   8000 characters each are required to export a complete VARCHAR(MAX) variable.
#'   It then creates the necessary number of intermediate variables and queries the 
#'   data using the SQL Server \code{SUBSTRING} command, extracting the VARCHAR(MAX)
#'   variable in increments of 8000 characters. After completing the query, 
#'   the intemediary variables are concatenated and removed from the data.
#'   
#'   The function makes accommodation for multi-part queries as far as [TABLE].[VARIABLE]
#'   formats are concerned. It is not intended for use in [SCHEMA].[TABLE].[VARIABLE]
#'   formats. This at least allows \code{from} to include joins for more complex 
#'   queries.  Parameterized queries are also supported through \code{sqlExecute}.
#'
#' @export

query_varchar_max <- function(channel, id, varchar_max, from, 
                              stringsAsFactors = FALSE, ...)
{
  coll <- checkmate::makeAssertCollection()

  checkmate::assert_class(x = channel,
                          classes = "RODBC",
                          add = coll)

  checkmate::assert_character(x = id,
                              add = coll)

  checkmate::assert_character(x = varchar_max,
                              add = coll)

  checkmate::assert_character(x = from,
                              len = 1,
                              add = coll)

  checkmate::assert_logical(x = stringsAsFactors,
                            len = 1,
                            add = coll)

  checkmate::reportAssertions(coll)

  varchar_max_len <-
    paste0(
      sprintf("MAX(LEN(%s)) AS len_%s", 
              varchar_max,
              sub("[.]", "_", varchar_max)),
      collapse = ", "
    )

  varchar_len <- 
    unlist(
      RODBCext::sqlExecute(
        channel = channel,
        query = sprintf("SELECT %s %s",
                        varchar_max_len,
                        from),
        fetch = TRUE
      )
    )

  varchar_max_cols <- 
    unlist(
      mapply(expand_varchar_max,
             varchar_max,
             varchar_len,
             SIMPLIFY = FALSE)
    )

  Prelim <- 
    RODBCext::sqlExecute(
      channel = channel,
      query = sprintf("SELECT %s, %s %s",
                      paste0(id, collapse = ", "), 
                      paste0(varchar_max_cols, collapse = ", "),
                      from),
      fetch = TRUE,
      stringsAsFactors = stringsAsFactors,
      ...
    )

  var_stub_to_combine <-
    unique(
      sub(
        "(part)(\\d{1,3})", 
        "\\1",
        sub(".+AS ", "", varchar_max_cols)
      )
    )

  col_to_combine <- 
    lapply(var_stub_to_combine,
           grep,
           names(Prelim))

  Prelim[sub(".+[.]", "", varchar_max)] <-
    lapply(col_to_combine,
           function(col) apply(Prelim[col], 1, paste0, collapse = ""))

  Prelim[-unlist(col_to_combine)]

}


expand_varchar_max <- function(varchar_max, varchar_len)
{
  nvar <- varchar_len %/% 8000 + 1

  var_list <- vector("character", length = nvar)

  for (i in seq_along(var_list))
  {
    var_list[i] <- 
      sprintf("SUBSTRING(%s, %s, %s) AS %s_part%s",
              varchar_max,
              1 + (i - 1) * 8000,
              8000,
              paste0(sub("[.]", "_", varchar_max)),
              i)
  }
  var_list
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

RODBC 和 Microsoft SQL Server:截断长字符串 的相关文章

  • R 未获取用户库

    我有一个带 R 3 6 0 的 Fedora 30 系统 用户库设置在Renviron就像这个 R LIBS USER R LIBS USER R x86 64 redhat linux gnu library 3 6 事实上 它出现在交互
  • 如何在R中的2行之间交换多个值

    我有一个大小为 10x100 的矩阵 如何交换前 30 列中第 1 行和第 2 行之间的值 我们可以反转前两行的行索引以及通过采取序列创建的列索引rounded 30 总列数用于交换行中的值 colS lt seq round ncol m
  • 通过 rpy 将 SPSS 文件(.sav)导入 pandas 时如何保留标签?

    我正在寻找使用 SPSS 文件 sav pandas 在没有 SPSS 程序的情况下 典型文件转换为 csv 后的样子如下 在调查前两行的含义时 我不知道 SPSS 似乎第一行包含Labels 而第二行包含VarNames 当我将文件带入
  • R(或替代方案?)中的高(或非常高)阶多项式回归

    我想对 R 中的一组数据进行 非常 高阶回归拟合 但是poly 函数的阶数极限为 25 对于此应用程序 我需要的订单范围为 100 到 120 model lt lm noisy y poly q 50 Error in poly q 50
  • 如何使用 R 或 PowerShell 从文本文件中提取数据?

    我有一个包含如下数据的文本文件 This is just text Username SOMETHI C Text Account DFAG Finish time 1 JAN 2011 00 31 58 91 Process ID 202
  • R 在读取文件时添加额外的数字

    我一直在尝试读取一个包含日期字段和数字字段的文件 我的数据在 Excel 工作表中 如下所示 Date X 1 25 2008 0 0023456 12 23 2008 0 001987 当我在 R 中使用readxl read xlsx函
  • 不理解..密度的行为

    在下面的数据框中 我预计密度的 y 轴值为 0 6 和 0 4 但它们是 1 0 我觉得我使用的方式显然缺少一些非常基本的东西 密度 但是我的大脑冻结了 我将如何使用 密度 获得所需的行为 任何帮助将不胜感激 df lt data fram
  • Sql Server 字符串到日期的转换

    我想像这样转换一个字符串 10 15 2008 10 06 32 PM 转换为 Sql Server 中的等效 DATETIME 值 在 Oracle 中 我会这样说 TO DATE 10 15 2008 10 06 32 PM MM DD
  • TSQL 定义临时表(或表变量)而不定义架构?

    有没有一种方法可以定义临时表而无需预先定义其架构 实际上 使用表 VARIABLE 内存表 是最佳方法 table 在临时数据库中创建一个表 而 table 是全局的 两者都具有磁盘命中 考虑交易数量所经历的放缓 打击 CREATE PRO
  • 如何在 R 中绘制预测的子集?

    我有一个简单的 R 脚本来根据文件创建预测 自 2014 年以来就有数据记录 但我在尝试实现以下两个目标时遇到了困难 仅绘制预测信息的子集 从 11 2017 开始 以特定格式包含月份和年份 即 6 月 17 日 这是链接到dataset
  • R testthat 单元测试数据和辅助函数约定

    我正在编写一个 R 包 并使用 testthat 进行单元测试 我的许多单元测试都是为了测试适用于我的包特定对象的功能 对于这些测试 我创建了一个辅助函数来设置模拟对象 我还有一些其他辅助函数来减少单元测试中的代码量 目前这些辅助函数在我的
  • PDO dblib 未捕获警告

    我已经使用 realestateconz mssql bundle 和免费 TDS 成功使我的 symfony 应用程序连接到 MSSQL 数据库 我的问题是 当我尝试执行存储过程时 如果出现问题 该过程会引发异常 但 PDO 不会报告任何
  • 从频率表生成 data.frame

    我在 2 4 数组中有包含 500 个观察值的合成数据 datax array c 120 181 50 43 41 33 24 8 dim c 2 4 dimnames datax list gender c male female pu
  • R 抑制系统或 shell 命令的控制台输出

    我有这个 Windows 批处理文件 我使用 R 从 R 调用该文件shell 命令 该批处理文件执行一些计算并将它们写入磁盘上 也写入屏幕上 我只对磁盘输出感兴趣 我无法更改批处理文件 批处理文件可能有点愚蠢 例如 echo off ec
  • 通过删除连续的重复项来减少字符串长度

    我有一个包含 2 个字段的 R 数据框 ID WORD 1 AAAAABBBBB 2 ABCAAABBBDDD 3 我想通过仅保留字母而不是重复中的重复项来简化具有重复字母的单词 e g AAAAABBBBB应该给我AB and ABCAA
  • 为 Linux 安装 R 包时出错

    我试图在 R 3 3 上安装一个名为 rgeos 的包 但是当我输入 install packages rgeos 但它返回给我以下错误 其他包也会发生同样的情况 但不是所有包 gt installing source package rg
  • 如何更改数据表中的少数列名称

    我有一个包含 10 列的数据表 town tc one two three four five six seven total 需要生成我正在使用的列 一 到 总计 的平均值 DTmean lt DT lapply SD mean by t
  • 列的 SQL MAX(包括其主键)

    Short 从下面的 sql select 中 我获取了 cart id 和该购物车中最高价值商品的值 SELECT CartItems cart id MAX ItemValues value FROM CartItems INNER J
  • 如何在 R 树形图中省略标签?

    我一直在使用R 树形图包 http cran r project org web packages treemap treemap pdf我有一个 2 层深的树形图 我希望打印第二级标签 但不打印第一级标签 使用手册页中的示例 tmPlot
  • 将存储过程的结果加上额外的列插入表中

    如何在其中插入更多列dbFileListOnly表以及 EXEC 查询 INSERT INTO admindb dbfilelistonly path col1 col2 path EXEC RESTORE FILELISTONLY FRO

随机推荐

  • 增加字体真棒图标

    我在使用一些字体很棒的图标时遇到了一些麻烦 我正在尝试增加其中一些的大小 但由于某种原因 我似乎没有做任何事情 这是我的html div class span5 bookBuild div class well well small h4
  • 如何在 Javascript 中按 15 分钟间隔对 json 集合进行分组

    假设我们在 Javascript 中有一个这样的集合 date Fri 02 May 2014 19 05 00 GMT value abc date Fri 02 May 2014 23 43 00 GMT value jkl date
  • 显示自 master 的原始分支点以来 git 分支中的所有提交

    我正在寻找一种方法来查看自分支点 并包括它 以来活动分支上的所有提交 并希望自主分支以来 例如这样的情况 A B C D master E F branch A 我想要获得提交 F E 和 B 而 F 是 HEAD And for A B
  • Google Apps 脚本电子表格评论自动化

    今天我有一个关于 Google Apps 脚本的问题 特别是电子表格 我已经看过文档了here 是的 有关a的文档Sheet在电子表格中 但我一直无法找到我要找的东西 这是西奇 1 当在 Google 电子表格中编辑单元格时 我的函数会设置
  • 安装和运行 rcpp 时出错

    我对 R 还很陌生 所以对一个愚蠢的问题表示歉意 我正在尝试让 rcpp 运行 但我陷入了 R 的无限循环 要求我重新安装 RTools 我大致遵循了以下代码这篇博文 虽然第一次休息时我手动安装了所有东西 随后我又重新安装了几次 我正在运行
  • Java:负数右移

    我对负数的右移操作感到非常困惑 这是代码 int n 15 System out println Integer toBinaryString n int mask n gt gt 31 System out println Integer
  • 通过特定位置和经度获取屏幕坐标(android)

    我有一个增强现实的应用程序 其中存储了地铁 加油站 名胜古迹等信息以及相应的纬度和经度 现在 根据设备的方向 我将在设备的相机视图中显示每个站点的标记 类似于 Layar 和 Wikitude 找了三天没有间断 也没有找到人解释如何解决这个
  • 为什么 kinect 颜色和深度无法正确对齐?

    我已经研究这个问题很长一段时间了 并且我的创造力已经结束 所以希望其他人可以帮助我指明正确的方向 我一直在使用 Kinect 并尝试将数据捕获到 MATLAB 幸运的是 有很多方法可以做到这一点 我目前正在使用http www mathwo
  • 所有系统引用都缺少 Visual Studio 2013 NuGet Async

    我在 Visual Studio 2013 中设置了一个解决方案 团队项目 并且有一段时间为 NET Framework 4 0 安装了一个可用的 NuGet Microsoft Bcl 异步包 今天 当打开项目时 无法找到所有默认的 NE
  • 在@RequestParam中绑定列表

    我以这种方式从表单发送一些参数 myparam 0 myValue1 myparam 1 myValue2 myparam 2 myValue3 otherParam otherValue anotherParam anotherValue
  • 如何在选中时覆盖 Material UI 开关组件的样式?

    我想控制开关组件的颜色 无论是在选中还是未选中时 默认情况下它是红色的 我希望当开关状态为 球形旋钮 时为黄色checked true我希望它是灰色的 什么时候checked false I must通过使用来实现样式createMuiTh
  • 如何更改 Material-UI 滑块颜色

    我想更改 Material UI Slider 组件颜色 我尝试更改CSS样式但它不起作用 然后我尝试了中给出的解决方案this问题并应用了此代码 但它不起作用 获取Mui主题 const muiTheme getMuiTheme slid
  • Ruby 中的 Array.prototype.splice

    有朋友问我用Ruby最好 最高效的方式来达到JavaScript的效果spliceRuby 中的方法 这意味着不对数组本身或副本进行迭代 从索引开始处开始 删除长度项并 可选 插入元素 最后在数组中返回删除的项 这是误导性的 请参阅下面的
  • 创建android子项目时出错

    我通过安装了 cordova e Phonegapnpm install g 科尔多瓦 and npm install gphonegap分别 然后我通过创建了一个 HelloWorld 应用程序cordova 创建 HelloWorld
  • Android 4.0 中的 RemoteControlClient 是什么?

    我了解 StackOverflow 的规则 因此提前为提出这样的问题表示歉意主观问题 我尝试过文档但它说的是这样的 RemoteControlClient 允许公开要使用的信息 通过能够显示元数据 艺术品和媒体的远程控制 传输控制按钮 远程
  • 如何从 CefSharp 3 在本机浏览器中打开链接

    我需要在 CefSharp 3 的本机浏览器中打开链接 我需要在 CefSharp 3 的 chromium 浏览器中运行除表单之外的整个应用程序 当我单击表单的链接按钮 例如 注册按钮 它有一个指向注册表单的链接 时 我需要在本机浏览器
  • 带有 Flask 的 pyCUDA 给出 pycuda._driver.LogicError: cuModuleLoadDataEx

    我想在flask服务器 该文件直接使用即可正确运行python3但当使用相应的函数调用时失败flask 这是相关代码 cudaFlask py import pycuda autoinit import pycuda driver as d
  • 删除行后如何消除 rowid 编号中的间隙?

    Table tmp CREATE TABLE if not exists tmp id INTEGER PRIMARY KEY name TEXT NOT NULL 我插入了5行 select rowid id name from tmp
  • 如何检查嵌套引用中是否为 null

    寻找一些最佳实践指导 假设我有一行这样的代码 Color color someOrder Customer LastOrder Product Color 其中 Customer LastOrder Product 和 Color 可以是n
  • RODBC 和 Microsoft SQL Server:截断长字符串

    我正在尝试使用 R RODBC 从 Microsoft SQL Server 数据库查询变量 RODBC 正在将字符串截断为 8000 个字符 原始代码 截断为 255 个字符 根据 ODBC 文档 library RODBC con st