2009-09-09 3 views
7

Возможно ли выполнить массовую вставку в MS-SQL Server (2000, 2005, 2008) с использованием пакета RODBC?Массовая вставка MS-SQL с RODBC

Я знаю, что могу сделать это с помощью freebcp, но мне любопытно, реализует ли RODBC пакет этой части API Microsoft SQL, а если нет, то насколько сложно было бы реализовать его.

ответ

2

Возможно, вы ищете ?sqlSave, который использует параметризованный запрос INSERT INTO (выполняется в одной операции) при установке Fast=True.

+3

Nah, sqlSave сделает несколько ВСТАВКИ. Я хочу BULK INSERT, который является единственной транзакцией. – ephpostfacto

+0

делает fast = true, а не как транзакцию? – Tyler

+1

from rodbc docs: «логическое. Если false, записывайте данные по строке за раз. Если true, используйте параметризованный запрос INSERT INTO или UPDATE для записи всех данных за одну операцию». Однако, похоже, (при написании Netezza в моем случае) – Joe

2

Теперь Вы можете использовать dbBulkCopy из нового rsqlserver пакета:

Типичный сценарий:

  1. Вы можете создать матрицу
  2. вы сохранить его в виде файла CSV
  3. Вы называете dbBulkCopy к читать fil и вставлять его с помощью встроенного в программу bcp сервера MS Sql.

Это предположить, что ваша таблица уже создана в базе данных:

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 не находится на кране? – jangorecki

+1

@MusX, потому что он находится в разработке (специально для документации и тестирования), и он использует пакет 'rClr', который также не включен в CRAN. Но вам рекомендуется использовать его из GITHUB и будет рад любой обратной связи. – agstudy

1

Из всего, что я могу найти, никакое решения для массовой вставки в MySQL, и ничего, что работает с SSIS поэтому Microsoft включает аналитику в базе данных с SQL Server 2016 после покупки Revolution R Analytics.

Я попытался прокомментировать предыдущий ответ, но не имею репутации, чтобы сделать это.

Пакет rsqlserver должен работать с rClr, и ни один из этих пакетов не ведет себя хорошо, особенно потому, что функции INSERT rsqlserver имеют плохую обработку данных. Поэтому, если вы его используете, вы не знаете, что вы смотрите в таблице SQL, так как большая часть информации в вашем data.frame будет преобразована.

Учитывая RODBC пакет был вокруг в течение 15 лет, я очень разочарован тем, что никто не создал объемную функцию вставки ...

+1

важный момент на rsqlserver, но для многих из нас нам не нужно «смотреть» на данные (с точки зрения R). Если он был смоделирован и сформирован и обработан в R, нам просто нужен результат в базе данных, и не имеет значения, что R преобразует тип в базу данных (если они разумны и могут быть прочитаны другими системами) – Joe

1

Наш n2khelper пакет можно использовать bcp (bulkcopy), когда она доступна. Когда он недоступен, он возвращается к нескольким операторам INSERT.

Вы можете найти пакет на https://github.com/INBO-Natura2000/n2khelper

Установите его с devtools::install_git("INBO-Natura2000/n2khelper") и искать функции odbc_insert().

4

ознакомьтесь с новыми пакетами odbc и DBI. DBI::dbWriteTable пишет около 20 000 записей в секунду ... Много быстрее, чем вставки Row от 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 обрабатывает их как chunk.s –

+0

@PeterEllis Конечно, он создает инструкции INSERT INTO, но в этом выражении есть 1000 (chunksize) значений строк. Таким образом, он работает без ограничений (данных)/chunksize. Предположим, мы имеем hava данные, содержащие 50 тыс. Строк. Он отправляет 50 запросов вместо запроса 50000 в базу данных. Таким образом, происходит значительное увеличение скорости. – Sab

0

Использование RODBC, быстро вставить нам удалось создать (260 миллионов строк врезку) выглядит следующим образом (в R псевдокоде):

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 может читать.

Смежные вопросы