2016-03-24 3 views
1

Итак, есть много проблем в StackOverflow с проблемой RODBC, но я не видел этого конкретного варианта попытки добавить к SQL-дате SQL. Я действительно думаю, что должен быть параметр, который позволяет вам идентифицировать KEY и НЕ пытаться загрузить в это ... Я бы подготовил запрос на перенос, но RODBC не имеет ветви dev на github? В любом случае, я отправлю свою проблему и то, что я пытался сделать, а затем мое неприятное обходное решение.Невозможно использовать RODBC :: sqlSave на Azure SQL db

У меня есть данные в таблице под названием ActDF.new Вот свойство:

str(ActDF.new) 
'data.frame': 52 obs. of 10 variables: 
$ Date   : Date, format: "2016-03-23" "2016-03-23" "2016-03-23" "2016-03-23" ... 
$ Project  : Factor w/ 1 level "x": 1 1 1 1 1 1 1 1 1 1 ... 
$ IndName  : Factor w/ 26 levels "x x...etc",..: 2 17 1 4 11 12 8 3 25 6 ... 
$ IndNum  : num 1 2 3 4 5 6 7 8 9 10 ... 
$ ProjectYear : Factor w/ 2 levels "bla","blabla": 1 1 1 1 1 1 1 1 1 1 ... 
$ Value   : num NA NA NA NA 4883 ... 
$ NoteTitle  : Factor w/ 1 level "": 1 1 1 1 1 1 1 1 1 1 ... 
$ NoteAnnotation: Factor w/ 1 level "": 1 1 1 1 1 1 1 1 1 1 ... 
$ ID   : num 1 1 1 1 1 1 1 1 1 1 ... 
$ CorpCode  : ch 

Я хочу APPEND этой информации в БД, с довольно новым столом под названием Actuals. Поэтому я попытался использовать RODBC :: sqlSave для этого. Ниже найти методичный:

Подключение к БД

d <- "Actuals RW" 
p <- "xx" 
u <- "xx" 
channel <- odbcConnect(d,u,p) 

Получить количество строк на дб (чтобы знать, где KEY должен начать)

PresentNum <- sqlQuery(channel, 'SELECT count(*) FROM Actuals', rows_at_time = 5) 
PresentNum <- PresentNum[1,1] 

ОК, так давайте добавим идентификатор к моему DF, но также, есть тонны для ВПЛ ценности ... и я не нуждаюсь в них, так что давайте преобразуем к лучшему DF

## Initialize ID on this df 
ActDF.new$ID <- 1 

## Remove NAs from ActDF.new, and organize 
toSave <- ActDF.new %>% filter(!is.na(Value)) %>% 
    select (ID,Date,Project,FiscalYear=ProjectYear,IndNum,IndName,CorpCode,CurrentValue=Value,NoteTitle,NoteAnnotation) 

## And now issue correct numbers to the ID 
toSave$ID <- (PresentNum+1):(nrow(toSave)+PresentNum) 

Есть много пустых значений, так что давайте преобразуем тех NA (это раздражает способ сделать это ... Я знаю)

toSave <- 
    apply(toSave, 2, function(x) gsub("^$|^ $", NA, x)) %>% as.data.frame() 

## Now everything is a factor, convert to correct format 
toSave$ID <- as.numeric(toSave$ID) 
toSave$Date<- as.Date(toSave$Date) 
toSave$Project<- as.character(toSave$Project) 
toSave$FiscalYear<- as.character(toSave$FiscalYear) 
toSave$IndNum<- as.character(toSave$IndNum) 
toSave$IndName<- as.character(toSave$IndName) 
toSave$CorpCode<- as.character(toSave$CorpCode) 
toSave$CurrentValue<- as.numeric(toSave$CurrentValue) 
toSave$NoteTitle<- as.character(toSave$NoteTitle) 
toSave$NoteAnnotation <- as.character(toSave$NoteAnnotation) 

### OK, мы готовы! Поэтому постарайтесь добавить! ###

################# Test 1 TRY APPENDING DATA AS IS 
sqlSave(channel, toSave, tablename = 'Actuals', append = T, 
     rownames = F, colnames = F, verbose = T, 
     safer = T, addPK = F, 
     fast = T, test = F) 
### RETURNS ERROR: Cannot insert explicit value for identity column in table 'Actuals' when IDENTITY_INSERT is set to OFF. 

... Да ладно ...

################# Test 2 TRY TO CHANGE THE IDENTITY_INSERT PROPERTY 

sqlQuery(channel, "Set IDENTITY_INSERT Actuals ON", errors = TRUE) 
### RETURNS ERROR: Cannot find the object \"Actuals\" because it does not exist or you do not have permissions." 

Ох ... но ... ждать, что? Таблица точно существует, и у меня есть права RW. Так что, возможно, IDENTITY_INSERT как-то по-другому ... каков статус в любом случае?

sqlQuery(channel, "SELECT OBJECTPROPERTY(OBJECT_ID('Actuals'), 'TableHasIdentity')") 
### RETURNS 1. 

Huh. Не знаю, что это значит ... давайте снова попробовать ж/различные addPK настройки

################# Test 3, try to use addPK = TRUE to see if it makes difference. 
sqlSave(channel, toSave, tablename = 'Actuals', append = T, 
     rownames = F, colnames = F, verbose = T, 
     safer = T, addPK = T, 
     fast = T, test = F) 
### RETURNS ERROR: Cannot find the object \"Actuals\" because it does not exist or you do not have permissions." 

Это не раздражает вообще. OK FINE, давайте удалим ID все вместе

################# Test 4, Try to remove the ID 
NoID <- toSave[,-grep("ID",names(toSave))] 

sqlSave(channel, NoID, tablename = 'Actuals', append = T, 
     rownames = FALSE, colnames = FALSE, verbose = T, 
     safer = TRUE, addPK = F, 
     fast = T, test = F) 
### RETURNS ERROR: Error in odbcUpdate(channel, query, mydata, coldata[m, ], test = test, : missing columns in 'data' 

О, действительно? Там отсутствуют колонки ???????? FINE

## So add back in a dummy column 
NoID$dummy <- 0 
sqlSave(channel, NoID, tablename = 'Actuals', append = T, 
     rownames = FALSE, colnames = FALSE, verbose = T, 
     safer = TRUE, addPK = F, 
     fast = T, test = F) 
### RETURNS ERROR: Error in odbcUpdate(channel, query, mydata, coldata[m, ], test = test, : missing columns in 'data' 

Установка fast=F возвращает ошибку: length of 'dimnames' [2] not equal to array extent

OK. gg sqlSave Вы выигрываете, я проигрываю. Здесь я думаю, что модификация в порядке ...проверка SQL запрос, который он строит, мы видим:

Query: INSERT INTO "Actuals" ("ID", "Date", "Project", "FiscalYear", "IndNum", "CorpCode", "CurrentValue", "NoteTitle", "NoteAnnotation", "IndName") VALUES (?,?,?,?,?,?,?,?,?) 

Я думаю, что должен быть какой-то параметр, где я мог бы просто указать, что запрос к НЕ попытаться добавить к колонке ID ... правильно?

Я что-то упустил?

ответ

1

Это была моя работа вокруг:

################# Test 5, Try issuing the append command manually: 

Q <- "INSERT INTO \"Actuals\" (\"Project\", \"FiscalYear\") VALUES ('test','hello');" 
sqlQuery(channel, Q, errors = TRUE) 

Ok, так что работает! (поэтому я знаю, что это не проблема разрешения). Именно этот формат: Ему нужны двойные котировки для имен таблиц/полей и SINGLE для данных. ОК, так что теперь давайте попробуем применить эту логику к нашим реальным данным:

## first drop the dummy again: 
NoID <- NoID[,-grep("dummy",names(NoID))] 

## Ensure field names are surrounded by a DOUBLE quote, values are surrounded by a SINGLE quote. 
## Separate out the Date field because `paste` converts it to character if it's in with the rest of the data. 

Q <- paste(
    "INSERT INTO \"Actuals\" (\"Date\", \"Project\", \"FiscalYear\", \"IndNum\", \"IndName\", \"CorpCode\", \"CurrentValue\", \"NoteTitle\", \"NoteAnnotation\")", 
    " VALUES ('", NoID[1,1], "','", paste(NoID[1,2:ncol(NoID)],collapse="','"), 
    "')", sep="") 

sqlQuery(channel, Q, errors = TRUE) 

Наконец !! хорошо, это работает. Теперь сделать для всех ФР, но объединение> 2 символа векторы попарно сложно ... так:

## first create a character vector for each row, with the quotation marks nicely blended. 
crazyD <- "" 
for(i in 1:ncol(NoID)){ 
    crazyD <- paste(crazyD,paste("'",NoID[,i],"'", sep=""),sep="") 
} 
crazyD <- gsub("''","','",crazyD) 

## And now combine that one with the titles 
Q <- paste(
    "INSERT INTO \"Actuals\" (\"Date\", \"Project\", \"FiscalYear\", \"IndNum\", \"IndName\", \"CorpCode\", \"CurrentValue\", \"NoteTitle\", \"NoteAnnotation\") VALUES (", 
    crazyD, ")", collapse="; ") 

## And push that query into the server 
sqlQuery(channel, Q, errors = TRUE) 

И вот как я это сделаю. Думаю, пока кто-то не скажет мне, как это сделать лучше. До тех пор, что будет держать меня вверх: Maximum size for a SQL Server Query? IN clause? Is there a Better Approach

+0

Вам действительно нужно избегать всех двойных кавычек, например. '\" «Я сочувствую, но не удивляюсь и могу рассказать вам по опыту, что предложения об улучшениях/изменениях в RODBC по существу бесполезны. – joran

+0

Насколько я знаю, вы можете« сделать некоторые »конкретные« вещи »или наоборот, но так как мне нужны ОБОИХ двойные и одинарные кавычки, я не знаю, как это сделать, а не ускользнуть и ускользнуть ... почему RODBC не отвечает? Я не думаю, что мой запрос «Пожалуйста, позвольте мне опционально не писать в мою связанную поле "нелепо, не так ли? –

+0

Я просто говорю, что в моем личном опыте сторонник этого пакета почти не интересовался развлекательными изменениями, которые увеличивают или улучшают функциональность. Я не знаю почему. Возможно, другие люди могут Мне повезло больше, чем у меня. – joran