Пакетное обновление ADO в Access VBA

Я пытаюсь использовать пакетные обновления в Access VBA. Мой код отлично работает, когда я обновляю его после каждой операции, но терпит неудачу, когда я пытаюсь работать с несколькими строками. Исключение, которое я получаю, это

«Ошибка времени выполнения '-2147217887 (80040e21)': многоэтапная операция OLE DB вызвала ошибки. Проверьте каждое значение состояния OLE DB, если оно доступно. Никаких действий выполнено не было».

Мой код

rs.Open "dbrammDump", CurrentProject.Connection, _
            adOpenKeyset, adLockBatchOptimistic
rowsDel = 0
Do Until rs.RecordCount < 1
    rs.MoveFirst
    rs.Delete

    rowsDel = rowsDel + 1
Loop
rs.UpdateBatch

Есть идеи, в чем проблема?


person jwoolard    schedule 25.06.2009    source источник


Ответы (3)


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

Я предпочитаю задавать свойства объекта набора записей индивидуально, поскольку считаю, что его легче читать (и, следовательно, отлаживать), чем использовать перегруженный метод Open. Кроме того, вы можете использовать свойство RecordCount для своего цикла, например.

With rs
  .ActiveConnection = CurrentProject.Connection
  .Source = "dbrammDump"
  .CursorLocation = adUseClient  ' <<< THIS MISSING FROM ORIGINAL CODE
  .CursorType = adOpenKeyset
  .LockType = adLockBatchOptimistic
  .Open

  Dim counter As Long
  For counter = 0 To .RecordCount - 1
      .Delete
      .MoveNext
  Next

  .UpdateBatch

  rowsDel = counter

End With

FWIW Я согласен с другими здесь, что решение на основе наборов в SQL предпочтительнее процедурного кода, такого как приведенный выше.

person onedaywhen    schedule 26.06.2009
comment
Вы знаете, я не думаю, что это сделает пакетное обновление, если вы сначала не отключите набор записей. После .Open нужно сделать Set .ActiveConnection = Nothing, затем перед .UpdateBatch сделать Set .ActiveConnection = CurrentProject.Connection. - person ErikE; 20.01.2011
comment
Хм... Кажется, я пока не могу заставить работать отсоединенные наборы записей. Так что, возможно, мой комментарий был преждевременным. - person ErikE; 20.01.2011
comment
Ага! Я не использовал adLockBatchOptimistic. adLockOptimistic предотвращает работу пакетных обновлений. - person ErikE; 20.01.2011
comment
@Emtucifor: пакетные обновления должны работать независимо от того, подключены они или отключены, при условии, что вы используете adLockBatchOptimistic (и что поставщик и/или источник OLE DB поддерживает это). - person onedaywhen; 21.01.2011
comment
Да, именно такого типа замка мне не хватало. Извините за дезинформацию. Теперь, когда я перешел к вопросу о типе блокировки, я вижу, что вам не нужно отключать набор записей, чтобы предотвратить обновления при внесении изменений. - person ErikE; 21.01.2011

Почему вы удаляете записи таким образом, когда вы можете позвонить myconnection.Execute "DELETE FROM myTable WHERE....."?

Кроме того, как вы открыли набор записей? Вставьте сюда оператор myrecordset.Open(...).
Посмотрите, поможет ли эта ссылка.

person shahkalpeshp    schedule 25.06.2009
comment
Правда, так было бы лучше для данного случая (спасибо :-). Однако я также вставляю несколько тысяч строк и хотел бы делать это пакетно, а не по отдельности. - person jwoolard; 25.06.2009
comment
Является ли источником ваших вставок набор данных, который можно использовать в операторе SELECT для добавления в виде пакета? Если да, то это ваш ответ. - person David-W-Fenton; 25.06.2009

Является ли источником ваших вставок набор данных, который можно использовать в операторе SELECT для добавления в виде пакета? Если да, то это ваш ответ.

Если вам нужно количество строк, удаленных/вставленных/обновленных с помощью кода ADO, используйте следующее.

CurrentProject.Connection.Execute strSQL, lngRecordsAffected, adCmdText
person Tony Toews    schedule 25.06.2009