Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server RODBC使用sqlSave对MS SQL失去数字列的精度(并在日期失败)_Sql Server_R_Rodbc_Significant Digits - Fatal编程技术网

Sql server RODBC使用sqlSave对MS SQL失去数字列的精度(并在日期失败)

Sql server RODBC使用sqlSave对MS SQL失去数字列的精度(并在日期失败),sql-server,r,rodbc,significant-digits,Sql Server,R,Rodbc,Significant Digits,为什么RODBC在使用sqlSave保存到ms sql时会丢失我的数字列的精度 数字 在R中,我使用一个数字列创建以下数据帧。它们可能看起来已经四舍五入了,但这是一个印刷问题,它们不是四舍五入的 >test <- data.frame( id=c(1,2,3), numbers=c(12345678.90,12345678.91,12345678.92) ) > str(test) 'data.frame': 3

为什么RODBC在使用sqlSave保存到ms sql时会丢失我的数字列的精度

数字 在R中,我使用一个数字列创建以下数据帧。它们可能看起来已经四舍五入了,但这是一个印刷问题,它们不是四舍五入的

>test <- data.frame(
          id=c(1,2,3),
          numbers=c(12345678.90,12345678.91,12345678.92)
          )
> str(test)
'data.frame':   3 obs. of  2 variables:
 $ id     : num  1 2 3
 $ numbers: num  12345679 12345679 12345679
> test$numbers==123456789
[1] FALSE FALSE FALSE
日期 日期类列导致浮点类型的ms sql列,从而导致存储不正确的值:

> test <- data.frame(id=c(1,2,3),date=as.Date(c("2014-12-21","2014-12-22","2014-12-23")))
> sqlSave(dbconn, test, fast=F, verbose=T)
Query: CREATE TABLE "test"  ("rownames" varchar(255), "id" float, "date" float)
Query: INSERT INTO "test" ( "rownames", "id", "date" ) VALUES ( '1', 1, 2014-12-21 )
Query: INSERT INTO "test" ( "rownames", "id", "date" ) VALUES ( '2', 2, 2014-12-22 )
Query: INSERT INTO "test" ( "rownames", "id", "date" ) VALUES ( '3', 3, 2014-12-23 )

> test2<-sqlFetch(dbconn, "test")
> test2
   id date
 1  1 1981
 2  2 1980
 3  3 1979


在RODBC的代码中,似乎有内部调用在as.matrix.dataframe中取消列表,这可以解释这个问题:

> unlist(list(test))
     id1      id2      id3 numbers1 numbers2 numbers3 
       1        2        3 12345679 12345679 12345679 '
我最好的嘉宾是围绕RODBC工作,并作为varType逻辑控制到字符的转换

逻辑列被解释为varchar,我们可以很容易地将其转换为BIT

sqlSave2<-function(dbconn, dat, tablename = NULL, ...){
  # get the name of the variable passed as dat, taken from sqlSave implementation
  if (is.null(tablename)) 
    tablename <- if (length(substitute(dat)) == 1) 
      as.character(substitute(dat))
  else as.character(substitute(dat)[[2L]])
  if (length(tablename) != 1L) 
    stop(sQuote(tablename), " should be a name")
    varTypes <- sapply(dat, function(x){
    if(is.numeric(x)){
      "float"
      }else if(is.factor(x)|is.character(x)){
        paste0("[varchar](",max(nchar(as.character(x))),")")
        } else if(is.logical(x)){"BIT"} else if("Date"%in%class(x)) {
          "date"
          } else if ("POSIXt"%in%class(x)){
            "smalldatetime"
            }else{NA}})# let RODBC determine
  varTypes <- varTypes[!is.na(varTypes)]
  dat2<-as.data.frame(sapply(dat, function(x){
    if(is.numeric(x)){
      x2<-sprintf("%.15e",x)
      if(sum(is.na(x))>0)
        x2[is.na(x)]<-NA
      x2
    } else if(is.logical(x)){
      x2<-rep(0,length(x))
      x2[!is.na(x) & x==T]<-1
      if(sum(is.na(x))>0)
        x2[is.na(x)] <- NA
      x2
      } else as.character(x)
  }))
  sqlSave(dbconn, dat2, tablename, fast=FALSE, varTypes=varTypes, ...)
}
以下是:

> sqlSave2(dbconn, test)
Query: CREATE TABLE "test"  ("rownames" varchar(255), "id" float, "date" date, "datetime" smalldatetime)
Query: INSERT INTO "test" ( "rownames", "id", "date", "datetime" ) VALUES ( '1', 1.234567891200000e+08, N'2014-12-21', '2014-12-21 10:00:00' )
Query: INSERT INTO "test" ( "rownames", "id", "date", "datetime" ) VALUES ( '2', 1.234567892300000e+08, N'2014-12-22', '2014-12-22 11:00:00' )
Query: INSERT INTO "test" ( "rownames", "id", "date", "datetime" ) VALUES ( '3', 1.234567892300000e+08, N'2014-12-23', '2014-12-23 12:00:00' )
通过以下验证:

> test2<-sqlFetch(dbconn, "test")
> test2
         id       date            datetime
1 123456789 2014-12-21 2014-12-21 10:00:00
2 123456789 2014-12-22 2014-12-22 11:00:00
3 123456789 2014-12-23 2014-12-23 12:00:00
> str(test2)
'data.frame':   3 obs. of  3 variables:
 $ id      : num  1.23e+08 1.23e+08 1.23e+08
 $ date    : Factor w/ 3 levels "2014-12-21","2014-12-22",..: 1 2 3
 $ datetime: POSIXct, format: "2014-12-21 10:00:00" "2014-12-22 11:00:00" "2014-12-23 12:00:00"
> test2$id==123456789
[1] FALSE FALSE FALSE
>test2 test2
id日期日期时间
1 123456789 2014-12-21 2014-12-21 10:00:00
2 123456789 2014-12-22 2014-12-22 11:00:00
3 123456789 2014-12-23 2014-12-23 12:00:00
>str(test2)
“data.frame”:3个obs。共有3个变量:
$id:num 1.23e+08 1.23e+08 1.23e+08
$date:系数w/3等级“2014-12-21”、“2014-12-22”、..:1 2 3
$datetime:POSIXct,格式:“2014-12-21 10:00:00”“2014-12-22 11:00:00”“2014-12-23 12:00:00”
>test2$id==123456789
[1] 假假假假
> packageVersion("RODBC")
[1] ‘1.3.10’
> unlist(list(test))
     id1      id2      id3 numbers1 numbers2 numbers3 
       1        2        3 12345679 12345679 12345679 '
sqlSave2<-function(dbconn, dat, tablename = NULL, ...){
  # get the name of the variable passed as dat, taken from sqlSave implementation
  if (is.null(tablename)) 
    tablename <- if (length(substitute(dat)) == 1) 
      as.character(substitute(dat))
  else as.character(substitute(dat)[[2L]])
  if (length(tablename) != 1L) 
    stop(sQuote(tablename), " should be a name")
    varTypes <- sapply(dat, function(x){
    if(is.numeric(x)){
      "float"
      }else if(is.factor(x)|is.character(x)){
        paste0("[varchar](",max(nchar(as.character(x))),")")
        } else if(is.logical(x)){"BIT"} else if("Date"%in%class(x)) {
          "date"
          } else if ("POSIXt"%in%class(x)){
            "smalldatetime"
            }else{NA}})# let RODBC determine
  varTypes <- varTypes[!is.na(varTypes)]
  dat2<-as.data.frame(sapply(dat, function(x){
    if(is.numeric(x)){
      x2<-sprintf("%.15e",x)
      if(sum(is.na(x))>0)
        x2[is.na(x)]<-NA
      x2
    } else if(is.logical(x)){
      x2<-rep(0,length(x))
      x2[!is.na(x) & x==T]<-1
      if(sum(is.na(x))>0)
        x2[is.na(x)] <- NA
      x2
      } else as.character(x)
  }))
  sqlSave(dbconn, dat2, tablename, fast=FALSE, varTypes=varTypes, ...)
}
> test <- data.frame(
    id=c(123456789.12,123456789.23,123456789.23), 
    date=as.Date(c("2014-12-21","2014-12-22","2014-12-23")),
    datetime=as.POSIXlt(c("2014-12-21 10:00","2014-12-22 11:00","2014-12-23 12:00")))
> str(test)
'data.frame':   3 obs. of  3 variables:
 $ id      : num  1.23e+08 1.23e+08 1.23e+08
 $ date    : Date, format: "2014-12-21" "2014-12-22" "2014-12-23"
 $ datetime: POSIXct, format: "2014-12-21 10:00:00" "2014-12-22 11:00:00" "2014-12-23 12:00:00"
> sqlSave(dbconn, test, fast=F, verbose=T)
Query: CREATE TABLE "test"  ("rownames" varchar(255), "id" float, "date" float, "datetime" float)
Query: INSERT INTO "test" ( "rownames", "id", "date", "datetime" ) VALUES ( '1', 123456789, 2014-12-21, 2014-12-21 10:00:00 )
Error in sqlSave(dbconn, test, fast = F, verbose = T) : 
  42000 102 [Microsoft][ODBC SQL Server Driver][SQL Server]Incorrect syntax near '10'.
[RODBC] ERROR: Could not SQLExecDirect 'INSERT INTO "test" ( "rownames", "id", "date", "datetime" ) VALUES ( '1', 123456789, 2014-12-21, 2014-12-21 10:00:00 )'
> sqlSave2(dbconn, test)
Query: CREATE TABLE "test"  ("rownames" varchar(255), "id" float, "date" date, "datetime" smalldatetime)
Query: INSERT INTO "test" ( "rownames", "id", "date", "datetime" ) VALUES ( '1', 1.234567891200000e+08, N'2014-12-21', '2014-12-21 10:00:00' )
Query: INSERT INTO "test" ( "rownames", "id", "date", "datetime" ) VALUES ( '2', 1.234567892300000e+08, N'2014-12-22', '2014-12-22 11:00:00' )
Query: INSERT INTO "test" ( "rownames", "id", "date", "datetime" ) VALUES ( '3', 1.234567892300000e+08, N'2014-12-23', '2014-12-23 12:00:00' )
> test2<-sqlFetch(dbconn, "test")
> test2
         id       date            datetime
1 123456789 2014-12-21 2014-12-21 10:00:00
2 123456789 2014-12-22 2014-12-22 11:00:00
3 123456789 2014-12-23 2014-12-23 12:00:00
> str(test2)
'data.frame':   3 obs. of  3 variables:
 $ id      : num  1.23e+08 1.23e+08 1.23e+08
 $ date    : Factor w/ 3 levels "2014-12-21","2014-12-22",..: 1 2 3
 $ datetime: POSIXct, format: "2014-12-21 10:00:00" "2014-12-22 11:00:00" "2014-12-23 12:00:00"
> test2$id==123456789
[1] FALSE FALSE FALSE