RODBC:chars和numerics积极转换(有/无asis)

r2e*_*ans 5 r rodbc

/sf/answers/2329882481/相关,我发现从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
Run Code Online (Sandbox Code Playgroud)

在该示例中,我们看到了不期望的行为: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"
Run Code Online (Sandbox Code Playgroud)

如果其中至少有一个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
Run Code Online (Sandbox Code Playgroud)

不幸的是,数据模型不支持任意添加某些东西以鼓励这种行为(或者我只是没有想到这样做的好方法).数据模型是mychar包含的值011在字符方面不同的值.我发现的唯一解决方法是使用as.is = TRUE,这将需要我as.numeric所有相关的列,这既繁琐又(理论上)不必要的工作.

由于文档建议需要设置DBMSencoding,我检查了当前的编码(由/sf/answers/362772861/帮助):

sqlQuery(.conn, "SELECT SERVERPROPERTY('Collation')")
# 1 SQL_Latin1_General_CP1_CI_AS
Run Code Online (Sandbox Code Playgroud)

我已经使用(踢)尝试:DBMSencoding="latin1",DBMSencoding="UTF-8",并明确虽然默认DBMSencoding=""与行为没有任何变化.

如何鼓励不过度胁迫数据类型的行为?

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

nru*_*ell 8

如果我理解正确的话,我认为如果您正在寻找,

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
Run Code Online (Sandbox Code Playgroud)

where as.is指定为逻辑向量(必须与结果集中的列数具有相同的长度).公平地说,这并不是很清楚.man手册sqlQuery只是引用你的as.is参数read.table,其中指出:

请注意,as.is是按列(而不是每个变量)指定的,因此包括行名称列(如果有)和要跳过的任何列.

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