0

I'm using SQLOLEDB provider through ADODB to work with a SQLServer 2012R2 database using VBA running in Excel.

I have no problems navigating through a RecordSet generated from a SELECT statement generated through a RecordSet.Open method.

I recently started having a RecordSet returned from INSERT statements through the use of an OUTPUT clause to return the ID for a newly inserted Record. I then call the Connection.Execute method with the SQL statement and obtain a RecordSet from this with the new ID value.

If the table in which the new record was inserted has Primary Key(s) defined, then trying to call RecordSet.MoveFirst on this returned RecordSet results in the Primary Key Violation exception being thrown as a VBA Runtime error. If there are no Keys defined on the table, then I do not get the error.

I'm getting the error in a generic function that I wrote which iterates through the record set to pull out data into an application-specific object.
I'm using the RecordSet.MoveFirst method prior to looping through the RecordSet to make sure that I'm at the beginning of the RecordSet, just in case the RecordSet had been touched by another method that changed the cursor position.

I also call the MoveFirst method in another function that gets the number of Records in the RecordSet, since I couldn't find any other way with the default cursor to find out how many records there are. The exception is raised in either of these two methods, whenever MoveFirst is called.

I noticed that the RecordSet returned from the OUTPUT Clause has the .Source property set to the full INSERT statement that was originally issued.

The property RecordSet.LockType is adLockReadOnly and .EditMode is adEditNone.

One thing that I don't understand here is why MoveFirst would result in this behavior, where it seems to be trying to repeat the INSERT statement just because I'm moving the cursor. I don't think it's actually doing that, because when I try this on a table with no keys defined I do not get an extra duplicate record being inserted.

Advice? Perhaps there is a better way to manage cursor positioning and iterating through the RecordSet?

I suppose I could try placing an "On Error Resume Next" statement before calling MoveFirst, but that doesn't seem like a good solution, even if it would work.

4

1 回答 1

0

我最终调查了我正在使用的光标的效果。我并没有真正研究过这么多,只是使用了服务器提供的默认光标。将连接的 CursorLocation 属性更改为 adUseClient 使我可以毫无问题地调用 MoveFirst 方法。

这里有一小段代码只是为了展示我现在如何通过指定光标位置作为我所做的唯一更改来获取 RecordSet:

Dim conn As ADODB.Connection
Dim adoRS As ADODB.RecordSet
Set conn = New ADODB.Connection

On Error GoTo Catch
**conn.CursorLocation = adUseClient**  //added this line
conn.Open (ConnectionString)

Set adoRS = conn.Execute(SQLStatement)
//RecordSet inherits the cursor type from the connection
//Calling adoRS.MoveFirst multiple times now does not generate an error. 

但是,我从来没有弄清楚为什么服务器提供的游标具有引发异常的行为或使用服务器提供的游标解决它的方法。

于 2017-08-02T22:04:26.373 回答