2009-09-09 30 views
7

Có thể thực hiện chèn hàng loạt vào máy chủ MS-SQL (2000, 2005, 2008) bằng gói RODBC không?Chèn số lượng lớn MS-SQL với RODBC

Tôi biết rằng tôi có thể làm điều này bằng cách sử dụng freebcp, nhưng tôi tò mò nếu gói RODBC triển khai phần này của Microsoft SQL API và nếu không, sẽ khó khăn như thế nào để triển khai nó.

Trả lời

2

Có thể bạn đang tìm kiếm ?sqlSave sử dụng truy vấn INSERT INTO được parametrized (diễn ra trong một thao tác) khi bạn đặt Fast=True.

+3

Không, sqlSave sẽ thực hiện nhiều lần INSERTS. Tôi muốn có một INSUL BULK mà là một giao dịch duy nhất. – ephpostfacto

+0

thực hiện nhanh = true không thực hiện như một giao dịch đơn lẻ? – Tyler

+1

từ các tài liệu rodbc: "hợp lý. Nếu sai, ghi dữ liệu một hàng tại một thời điểm. Nếu đúng, hãy sử dụng truy vấn INSERT INTO hoặc UPDATE parametrized để ghi tất cả dữ liệu trong một thao tác." .. Tuy nhiên nó dường như không tạo ra bất kỳ sự khác biệt nào (khi viết thư cho Netezza trong trường hợp của tôi) – Joe

2

Bây giờ Bạn có thể sử dụng dbBulkCopy từ mới rsqlserver gói:

Một kịch bản tiêu biểu:

  1. Bạn tạo một ma trận
  2. bạn lưu nó như một tập tin csv
  3. Bạn gọi dbBulkCopy để đọc fil và chèn nó bằng cách sử dụng công cụ nội bộ bcp của máy chủ MS Sql.

này giả định rằng bảng của bạn đã được tạo ra trong cơ sở dữ liệu:

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

bất kỳ lý do gì khiến rsqlserver không nằm trên cran? – jangorecki

+1

@MusX vì nó đang được phát triển (đặc biệt là tài liệu và kiểm tra một phần) và nó sử dụng gói 'rClr' mà không phải là trên CRAN quá. Nhưng bạn được khuyến khích sử dụng nó từ GITHUB và sẽ hài lòng với bất kỳ phản hồi nào. – agstudy

1

Từ tất cả những gì tôi có thể tìm thấy, không có giải pháp cho số lượng lớn chèn để MySQL và không có gì mà làm việc với SSIS đó là lý do Microsoft bao gồm phân tích cơ sở dữ liệu trong SQL Server 2016 sau khi mua Revolution R Analytics.

Tôi đã cố gắng nhận xét về câu trả lời trước nhưng không có danh tiếng để làm điều đó.

Gói rsqlserver cần chạy với rClr và không phải gói nào trong số đó đều hoạt động tốt, đặc biệt vì chức năng INSERT của rsqlserver có xử lý loại dữ liệu kém. Vì vậy, nếu bạn sử dụng nó, bạn sẽ không có ý tưởng những gì bạn đang tìm kiếm trong bảng SQL càng nhiều thông tin trong data.frame của bạn sẽ được chuyển đổi.

Xét gói RODBC đã được khoảng 15 năm, tôi khá thất vọng mà không ai đã tạo ra một chức năng chèn số lượng lớn ...

+1

điểm quan trọng trên rsqlserver, nhưng đối với nhiều người trong chúng ta, chúng ta không cần phải 'xem xét' dữ liệu (từ quan điểm R). Nếu nó được mô hình hóa và định hình và xử lý trong R, chúng ta chỉ cần kết quả trong cơ sở dữ liệu và không quan trọng R biến đổi kiểu nào trong cơ sở dữ liệu (miễn là chúng hợp lý và có thể đọc được bởi các hệ thống khác) – Joe

1

gói n2khelper của chúng tôi có thể sử dụng bcp (bulkcopy) khi nó có sẵn. Khi không có sẵn, nó sẽ quay trở lại với nhiều câu lệnh INSERT.

Bạn có thể tìm thấy các gói trên https://github.com/INBO-Natura2000/n2khelper

Install nó với devtools::install_git("INBO-Natura2000/n2khelper") và tìm kiếm các odbc_insert() chức năng.

4

xem các gói odbcDBI mới. DBI::dbWriteTable ghi khoảng 20.000 bản ghi mỗi giây ... Nhanh hơn nhiều so với Chèn hàng từ RODBC::sqlSave()

-1

Chúng tôi đang sử dụng chức năng này để chèn bảng hàng loạt. Nó sử dụng gói RODBC và kết nối của nó.

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

I don 't xem cách này đang thực hiện tải lên hàng loạt. Nó không chỉ là tạo một truy vấn 'INSERT INTO ...' và gửi nó bằng 'sqlQuery'? Vì vậy, nó vẫn sẽ gửi nó một hàng tại một thời điểm, mặc dù R đang xử lý chúng như chunk.s –

+0

@PeterEllis Tất nhiên nó đang tạo ra một câu lệnh INSERT INTO nhưng có 1000 (chunksize) giá trị hàng trong câu lệnh đó. Vì vậy, nó hoạt động nrow (dữ liệu)/chunksize lần. Giả sử chúng ta có dữ liệu chứa 50 nghìn hàng. Nó gửi 50 truy vấn thay vì 50000 truy vấn tới cơ sở dữ liệu. Vì vậy, có một sự gia tăng đáng kể về tốc độ. – Sab

0

Sử dụng RODBC, chèn nhanh nhất, chúng tôi đã có thể tạo ra (260 triệu hàng chèn) trông giống như sau (trong R mã giả):

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;") 

Nếu bạn đang chạy này từ giữa các máy chủ, bạn cần một ổ đĩa mạng mà máy chủ R có thể ghi vào (ví dụ: một máy chủ có quyền ghi vào DB sử dụng Rscript để tạo mã) và SQL Server có thể đọc từ đó.

Các vấn đề liên quan