1

我正在创建一个闪亮的应用程序,用户需要使用闪亮的 FileInput 上传可能相当大的数据 (CSV)。然后我想将此数据保存到远程数据库。

现在我想知道以安全方式将数据导入远程数据库的最佳方法是什么?

  • 通过执行 dbWriteTable,数据库服务器在其自己的文件系统中查找文件,而不是在运行闪亮服务器的服务器中查找文件。

  • 通过首先将数据读入 R 然后执行 dbWriteTable 似乎效率很低。它还会导致闪亮的应用程序挂起,直到此过程完成。

任何建议将不胜感激。

4

1 回答 1

0

您可以使用如下函数,它依赖于 RODBC 包。但是你可以根据自己的需要进行修改。

sqlInsertBulk <- function(data, table, connString, chunksize = 1000)
{
  stopifnot(chunksize <= 1000)
  dbhandle <- odbcDriverConnect(connString)
  nrow_initial<-sqlQuery(dbhandle,paste("SELECT COUNT (1) FROM ",table)) 
  #If data includes Inf value, stop function.
  numericCols <- names(data)[sapply(data, is.numeric)]
  if (length(numericCols != 0)) {
    if(sum(unlist(data[,lapply(.SD, function(x) any(x == Inf)),.SDcols = numericCols]),na.rm=T)>0){
      stop("Data includes Inf value.")
    }
  }
  chunknumber <- ceiling(nrow(data)/chunksize)

  qstart <- paste("INSERT INTO ", table ," ( ",paste(colnames(data),collapse = ", "), " ) VALUES")

  for(chunki in 1:chunknumber)
  {
    chunkstart <- 1 + chunksize * ( chunki - 1 )
    chunkend <- min(nrow(data), chunki * chunksize )
    chunkdata <- data[chunkstart:chunkend]
    valuestring <- vector(mode="character", length=chunkend - chunkstart + 1 )
    for(i in 1:nrow(chunkdata)){
      valuestring[i] <- paste("(", paste(sapply(chunkdata[i], function(input){
        if(!class(input) %in% c("numeric", "integer")) {
          input<-paste0("'", input, "'")
        }
        if(is.na(input))
        {
          input<-"NULL"
        }
        return (input)
      }), collapse=", "), ")")
    }

    qend <- paste(valuestring, collapse = ", ")
    q <- paste(qstart, qend)
    print(paste("Chunk", chunki, "is in process."))
    up <- sqlQuery(dbhandle,q)
    if(length(up) > 0){
      stop(up)
    }
    print(paste("Chunk", chunki, "is uploaded."))
  }

  nrow_final <- sqlQuery(dbhandle,paste("SELECT COUNT (1) FROM ",table))
  odbcClose(dbhandle)

  if(nrow_final-nrow_initial==nrow(data)) {
    print(paste("All ",nrow(data)," data is uploaded."))
    return(T)
  } else {
    print(paste0("Warning!!! Only ",nrow_final-nrow_initial, " out of ",nrow(data), " are uploaded." ))
    return(F)
  }
}
于 2017-11-01T07:22:39.347 回答