SQL ServerCompactで動作する古いVB6コードを取得しようとしています。
接続してデータベースを開くことができますが、すべて問題ないようです。動作する挿入選択コマンドを実行できます。
ただし、フィールドにアクセスしてデータを表示できる場合でも、ADODB.RecordsetRecordCountプロパティは常に-1を返します。 CursorLocation = adUseClientを変更すると、SQLの実行時に問題が発生します(複数ステップの操作でエラーが発生しました)。
Option Explicit
Private Const mSqlProvider As String = "Provider=Microsoft.SQLSERVER.CE.OLEDB.3.5;"
Private Const mSqlHost As String = "Data Source=C:\Database.sdf;"
Private mCmd As ADODB.Command ' For executing SQL
Private mDbConnection As ADODB.Connection
Private Sub Command1_Click()
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
Dim DbConnectionString As String
DbConnectionString = mSqlProvider & _
mSqlHost
Set mDbConnection = New ADODB.Connection
mDbConnection.CursorLocation = adUseServer
Call mDbConnection.Open(DbConnectionString)
If mDbConnection.State = adStateOpen Then
Debug.Print (" Database is open")
' Initialise the command object
Set mCmd = New ADODB.Command
mCmd.ActiveConnection = mDbConnection
mCmd.CommandText = "select * from myTestTable"
mCmd.CommandType = adCmdText
Set rs = mCmd.Execute
Debug.Print rs.RecordCount ' Always returns -1 !!
Debug.Print rs.Fields(0) ' returns correct data for first row, first col
Debug.Print rs.Fields(1) ' returns correct data for first row, 2nd col
Debug.Print rs.Fields(2) ' returns correct data for first row, 3rd col
End If
End Sub
どんなアドバイスでもありがたく受け入れられます。
実際、この場合、CursorLocation
が主要な役割を果たします。使用する rs.CursorLocation = adUseClient
カーソル位置を設定して、試してください。
Set rs = New ADODB.Recordset
rs.CursorLocation = adUseClient
Dim DbConnectionString As String
DbConnectionString = mSqlProvider & _
mSqlHost
Set mDbConnection = New ADODB.Connection
mDbConnection.CursorLocation = adUseServer
Call mDbConnection.Open(DbConnectionString)
If mDbConnection.State = adStateOpen Then
Debug.Print (" Database is open")
' Initialise the command object
Set mCmd = New ADODB.Command
mCmd.ActiveConnection = mDbConnection
mCmd.CommandText = "select * from myTestTable"
mCmd.CommandType = adCmdText
Set rs = mCmd.Execute
Debug.Print rs.RecordCount ' This should now return the right value.
Debug.Print rs.Fields(0) ' returns correct data for first row, first col
Debug.Print rs.Fields(1) ' returns correct data for first row, 2nd col
Debug.Print rs.Fields(2) ' returns correct data for first row, 3rd col
End If
End Sub
これは、データへのアクセスに使用されるカーソルの種類の結果です。この投稿では、問題と可能な修正について説明します。
http://www.devx.com/tips/Tip/1414
[〜#〜]編集[〜#〜]
あなたがコンパクトを扱っていたという事実にもっと注意を払わなかったことをお詫びします。 Compactの場合、デフォルトで順方向のみのカーソル(行数をサポートしない)を使用するため、状況は私が参照した状況と似ていますが、以下のリンクに記載されているように、他に2つのカーソルタイプを使用できます。
Recordsetプロパティを確認する
以下は、com.status.liveコードによって返されたRecordCount値の結果です。
+------------------+-------------------+-------------+---------------+--------------+
| CursorTypeEnum|adOpenForwardOnly=0|dOpenKeyset=1|adOpenDynamic=2|adOpenStatic=3|
|CursorLocationEnum| |
+------------------+-------------------+-------------+---------------+--------------+
|adUseServer = 2 | X | O | X | O |
|adUseClient = 3 | O | O | O | O |
+------------------+-------------------+-------------+---------------+--------------+
これが私が使ったあなたのための解決策です
Dim recordnumber As Long
Dim SalRSrec As New ADODB.Recordset
Set SalRSrec = Nothing
SalRSrec.Open ("SELECT count(*) from SALARY where EMPID= '" & cmb_empid & "' ;"), Dbase, adOpenKeyset, adLockOptimistic
recordnumber = SalRSrec.GetString
MsgBox recordnumber
ずっと前にVB6/ADOを操作していたメモリから、レコードセットの最後に移動するまで、.RecordCountフィールドは意味のあるデータを返しません。
rs.MoveLast
rs.MoveFirst
Debug.Print rs.RecordCount
ただし、これを使用する場合は、適切なカーソルタイプがあることを確認する必要があります(つまり、前方だけではありません)。
私が考えることができる他の唯一の解決策は、myTestTableなどから個別のSELECT COUNT(*)を実行することですが、これには、その呼び出しと実際に行を返す呼び出しの間でデータが変更されるという問題があります。
それでも-1が返される場合は、次のコードを使用してみてください
Set Conn = createobject("ADODB.connection")
Set Rs = createobject("ADODB.recordset")
Conn.Open "DSN=DSN_QTP"
'Rs.Open "Select * From orders",Conn,adOpenDynamic,adLockBatchOptimistic
Rs.Open "Select * from [QTP-Table]",Conn,1 'Use either 1 or 3
'I tried using adopendynamic but it still returned -1. Using 1 it gave me correct count. 'Though I am using this code in QTP (Vbscript) same should work for VB6 also.
msgbox Rs.RecordCount
あなたはこのようなことを試みるかもしれません。
Set rs = mCmd.Execute
rs.MoveFirst
Do Until rs.EOF = true
Debug.Print rs.RecordCount ' Always returns -1 !!
Debug.Print rs.Fields(0) ' returns correct data for first row, first col
Debug.Print rs.Fields(1) ' returns correct data for first row, 2nd col
Debug.Print rs.Fields(2) ' returns correct data for first row, 3rd col
counter = counter + 1
rs.MoveNext
Loop
Compactでは、パフォーマンスを向上させるために、デフォルトのカーソル属性はadOpenForwardOnlyです。そのため、RecordCountは「-1」として返されます。これは、空白ではなく、使用できないことを意味します。これは仕様によるものです。動的カーソルのレコード数が変更され、クライアントサーバー間でpingが実行されて、精度が維持される可能性があるためです。ただし、レコード数が重要な場合は、サーバー側カーソルでadOpenKeysetまたはadOpenStaticを使用するように設定してみてください。
以下のコードが役立つかもしれません、
set conn = CreateObject("ADODB.Connection")
conn.open "<connection string>"
set rs = CreateObject("ADODB.Recordset")
sql = "SELECT columns FROM table WHERE [...]"
rs.open sql,conn,1,1
if not rs.eof then
nr = rs.recordcount
response.write "There were " & nr & " matches."
' ... process real results here ...
else
response.write "No matches."
end if
rs.close: set rs = nothing
conn.close: set conn = nothing
Set rs = mCmd.Execute
を次のように置き換えます。
set rs = new ADODB.Recordset
rs.Open "select * from myTestTable", mDBConnection, adOpenDynamic, adLockOptimistic
adOpenDynamic
を使用すると、順方向/逆方向のリードスルーでレコード数を取得できます。