我正在创建一个闪亮的应用程序,用户需要使用闪亮的 FileInput 上传可能相当大的数据 (CSV)。然后我想将此数据保存到远程数据库。
现在我想知道以安全方式将数据导入远程数据库的最佳方法是什么?
通过执行 dbWriteTable,数据库服务器在其自己的文件系统中查找文件,而不是在运行闪亮服务器的服务器中查找文件。
通过首先将数据读入 R 然后执行 dbWriteTable 似乎效率很低。它还会导致闪亮的应用程序挂起,直到此过程完成。
任何建议将不胜感激。
您可以使用如下函数,它依赖于 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)
}
}