2009-09-09 138 views
7

是否可以使用RODBC軟件包對MS-SQL Server(2000,2005,2008)執行批量插入?使用RODBC的MS-SQL批量插入

我知道我可以使用freebcp來做到這一點,但我很好奇RODBC軟件包是否實現了Microsoft SQL API的這一部分,如果不是,實現它將會有多困難。

回答

2

您可能正在尋找?sqlSave,當您設置Fast=True時,它使用參數INSERT INTO查詢(在一個操作中發生)。

+3

那麼,sqlSave會做多個INSERT。我想要一個BULK INSERT這是一個單獨的事務。 – ephpostfacto 2009-11-06 21:42:31

+0

does fast = true不是作爲單個事務處理嗎? – Tyler 2009-11-09 23:40:59

+1

from rodbc docs:「logical。If false,write data to a row at a time。If true,use an parametrized INSERT INTO or UPDATE query to write all the data in one operation。」但是它似乎沒有有什麼區別(在我的情況下寫入Netezza時) – Joe 2016-10-26 20:27:52

2

現在你可以使用dbBulkCopy從新rsqlserver包:

一個典型的例子:

  1. 您創建一個矩陣
  2. 將其保存爲CSV文件
  3. 你叫dbBulkCopy到讀取fil並使用MS Sql服務器的內部工具bcp插入它。

這假設你的表在數據庫中已經創建:

dat <- matrix(round(rnorm(nrow*ncol),nrow,ncol) 
id.file = "temp_file.csv"      
write.csv(dat,file=id.file,row.names=FALSE) 
dbBulkCopy(conn,'NEW_BP_TABLE',value=id.file) 
+0

爲什麼rsqlserver不在cran上? – jangorecki 2014-02-06 16:56:16

+1

@MusX因爲它正在開發中(特別是文檔和測試部分),它使用不在CRAN上的'rClr'軟件包。但是我們鼓勵您從GITHUB使用它,並會對任何反饋感到滿意。 – agstudy 2014-02-06 17:00:30

1

從一切我能找到,對於批量插入到MySQL並沒有什麼NO的解決方案,SSIS的工作這是爲什麼在購買Revolution R Analytics後,微軟將在SQL Server 2016中包含數據庫內分析功能。

我試着評論上一個答案,但沒有聲望去做。

rsqlserver包需要與rClr運行和既不那些包都表現良好的,特別是因爲rsqlserver的INSERT功能具有差的數據類型的處理。所以如果你使用它,你將不知道你在SQL表中看到什麼,因爲你的data.frame中的許多信息都將被轉換。

考慮到RODBC包已經有15年了,我很失望,沒有人創造了一個批量插入功能...

+1

重要的一點在rsqlserver上,但對於我們中的很多人來說,我們不需要'看'數據(從R的角度來看)。如果它已經在R中建模並進行了整形和處理,我們只需要將結果返回到數據庫中,並且R不會將數據類型轉換爲數據庫中的數據(只要它們合理並且可以被其他系統讀取) – Joe 2016-10-26 20:02:36

1

我們n2khelper包可以使用bcp(bulkcopy)可用時。如果不可用,它將回退到多個INSERT語句。

你可以找到https://github.com/INBO-Natura2000/n2khelper

包帶devtools::install_git("INBO-Natura2000/n2khelper")安裝它,並尋找odbc_insert()功能。

4

查看新的odbcDBI包。 DBI::dbWriteTable每秒寫入大約20,000條記錄......比行插入的速度快得多RODBC::sqlSave()

-1

我們使用此函數來插入批量表。它使用RODBC包和它的連接。

dbhandle <- odbcDriverConnect('driver={SQL Server};server=server...') 

sqlInsertBulk <- function(data, table, dbhandle,chunksize = 1000) 
{ 
    stopifnot(chunksize <= 1000) 
    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.")) 
    sqlQuery(dbhandle,q) 
    print(paste("Chunk", chunki, "is uploaded.")) 
    } 

    nrow_final <- sqlQuery(dbhandle,paste("SELECT COUNT (1) FROM ",table)) 
    if(nrow_final-nrow_initial==nrow(data)) { 
    print(paste("All ",nrow(data)," data is uploaded.")) 
    } else { 
    print(paste0("Warning!!! Only ",nrow_final-nrow_initial, " out of ",nrow(data), " are uploded.")) 
    } 
} 
+0

我不喜歡看不出這是如何進行批量上傳的。是不是隻是創建一個'INSERT INTO ...'查詢並通過'sqlQuery'發送它?所以它仍然會一次發送一行,即使R將它們作爲塊處理。 – 2017-12-05 04:55:16

+0

@PeterEllis當然,它創建了INSERT INTO語句,但在該語句中有1000個(塊)行值。 因此,它的工作原理(數據)/大塊時間。假設我們有一個數據包含50k行。它向數據庫發送50個查詢而不是50000個查詢。所以速度顯着增加。 – Sab 2017-12-05 07:23:40

0

使用RODBC,最快的插入,我們已經能夠創建(260萬行的插入)如下所示(在讀僞代碼):

ourDataFrame <- sqlQuery(OurConnection, "SELECT myDataThing1, myDataThing2 
             FROM myData") 
ourDF <- doStuff(ourDataFrame) 
write.csv(ourDF,ourFile) 
sqlQuery(OurConnection, "CREATE TABLE myTable (la [La], laLa [LaLa]); 
         BULK INSERT myTable FROM 'ourFile' 
           WITH YOURPARAMS=yourParams;") 

如果你正在運行此從服務器之間,您需要一個R服務器可以寫入的網絡驅動器(例如,一個具有寫入數據庫權限的服務器使用Rscript來生成代碼),並且SQL Server可以讀取。