RODBC:积极转换字符和数字(有/无原样)

Posted

技术标签:

【中文标题】RODBC:积极转换字符和数字(有/无原样)【英文标题】:RODBC: chars and numerics converted aggressively (with/without as.is) 【发布时间】:2016-07-18 17:58:51 【问题描述】:

与 https://***.com/a/33284035/3358272 相关,我发现从 SQL Server (2014) 中提取数据的行为不一致。

library(RODBC)
sqlQuery(.conn, "CREATE TABLE r2test ( [mychar] [NVARCHAR](16), [mynum] [FLOAT])")
# character(0)
sqlQuery(.conn, "INSERT INTO r2test (mychar,mynum) VALUES ('1',3.141593),('2',6.283185)")
character(0)
str(sqlQuery(.conn, "SELECT * FROM r2test", stringsAsFactors = FALSE))
# 'data.frame': 2 obs. of  2 variables:
#  $ mychar: int  1 2
#  $ mynum : num  3.14 6.28

在该示例中,我们看到了不希望的行为:mychar 的字符在内部被转换为整数。根据前面提到的 SO 答案,as.is 选项可以解决这个问题,但也有一个不幸的副作用,即强制将十进制表示的浮点数转换为字符串:

str(sqlQuery(.conn, "SELECT * FROM r2test", stringsAsFactors = FALSE, as.is = TRUE))
# 'data.frame': 2 obs. of  2 variables:
#  $ mychar: chr  "1" "2"
#  $ mynum : chr  "3.1415929999999999" "6.2831849999999996"

如果mychar 中的至少一个实际上不可整数化,则一切正常:

sqlQuery(.conn, "INSERT INTO r2test (mychar,mynum) VALUES ('a',9.424778)")
# character(0)
str(sqlQuery(.conn, "SELECT * FROM r2test", stringsAsFactors = FALSE))
# 'data.frame': 3 obs. of  2 variables:
#  $ mychar: chr  "1" "2" "a"
#  $ mynum : num  3.14 6.28 9.42

不幸的是,数据模型不支持任意添加一些东西来鼓励这种行为(或者我只是没有想到一个足够好的方法来做到这一点)。该数据模型使得mychar 的值包括011,它们在字符方面是不同的。我发现的唯一解决方法是使用 as.is = TRUE,这将要求我 as.numeric 所有相关列,这既乏味又(理论上)不必要的工作。

由于文档建议需要设置DBMSencoding,我检查了当前编码(由https://***.com/a/5182469/3358272 帮助):

sqlQuery(.conn, "SELECT SERVERPROPERTY('Collation')")
# 1 SQL_Latin1_General_CP1_CI_AS

我尝试使用(用于踢球):DBMSencoding="latin1"DBMSencoding="UTF-8",并明确使用默认的DBMSencoding="",但行为没有任何变化。

如何鼓励不要过度强制数据类型的行为?

目前在 ubuntu 上使用 R-3.2.5 和 RODBC-1.3.13。

【问题讨论】:

【参考方案1】:

如果我理解正确,我认为这就是你要找的,

str(sqlQuery(
  .conn, 
  "SELECT * FROM r2test", 
  stringsAsFactors = FALSE,
  as.is = c(TRUE, FALSE)
))
#'data.frame':  2 obs. of  2 variables:
# $ mychar: chr  "1" "2"
# $ mynum : num  3.14 6.28

其中as.is 被指定为逻辑向量(必须与结果集中的列数具有相同的长度)。公平地说,这并没有很好地说明。 sqlQuery 的手册页只是将您引向 read.table 中的 as.is 参数,其中指出:

注意 as.is 是按列指定的(而不是按变量),所以 包括行名列(如果有)和任何列 跳过。

这种方法的缺点是您需要提前知道要转换哪些列以及不转换哪些列。我个人不明白 为什么 默认行为不仅仅是将 SQL 字符类型映射到 R 字符类型、将 SQL 数字类型映射到 R 数字类型等,但也许有一个很好的理由在后端。自动将'1', '2', ... 转换为整数 不是 对我来说似乎是一个很大的“功能”。

【讨论】:

我没有考虑过使用逻辑 vector,它确实稍微改善了一些情况,提供了更直接的出路,谢谢!同意“不明白为什么”,但话又说回来,我(还没有)提供编写代码(并提交 PR)来以不同的方式处理事情。 是的,当函数参数的默认值为 TRUEFALSE 但也接受逻辑 向量 时,这有点令人困惑。同上,我对这个软件包有一个长期的看法,即 sqlUpdate 没有像宣传的那样工作,但我还没有开始着手开发补丁,所以我不能大声抱怨......跨度> nrussell,除了 R-sigs-db,您知道任何其他 RODBC 特定的讨论论坛吗?问题和 PR 的源代码?我想讨论参数化查询、部分表 sqlSave 以及其他不必要地限制我使用 RODBC 的事情。 我不知道有什么不幸的——我看到的这个包的唯一存储库是在 CRAN 的只读 GitHub 镜像上,但这只是 CRAN 自动导出的东西,而不是发展通道。但是,您可以考虑通过说明文件中列出的电子邮件联系 Brian Ripley。开发可能通过 SVN 或其他方式进行,但无论如何,作为当前的维护者,我想他将是谈论此事的最佳人选。我也对这些功能感兴趣,因为我在工作中花费大量时间使用 SQL (Server)。

以上是关于RODBC:积极转换字符和数字(有/无原样)的主要内容,如果未能解决你的问题,请参考以下文章

为啥在有符号和无符号表示之间转换一个数字?

c语言,编程实现,把输入的一行字符原样输出,若是大写字母则转换成小写字母

如何将带有尾随x的数字字符串转换为无符号数字列表

python 输入一个字符,是小写转换为大写,大写转换为小写,其他字符原样输出

无符号整型和有符号整形转换

printf()函数输出啥类型的数据?