В документации четко сказано, что, если вы откроете Recordset
, который не имеет записей:
BOF
будет истинным
EOF
будет истинным
RecordCount
будет 0
Для непустого Recordset
, ни BOF
, так и EOF
верны, пока вы не перейдете за первую или последнюю запись.
Может быть, кто-то еще мог добавить/удалить запись в одну из таблиц в наборе записей, который вы только открываете и меняете набор результатов?
Это может быть результат гонки.
Вместо использования BOF
или EOF
, вы можете проверить на Recordcount
: это всегда 0
если записи пусты.
Если набор записей не пуст, он, как правило, возвращает 1
сразу после открытия набора записей; Recordcount
не является дорогостоящей операцией в этом случае.
Единственный способ действительно вернуть номер, чтобы указать номер MoveLast
, прежде чем звонить Recordcount
, чтобы заставить все записи быть загружены.
Обычно, если мне нужно перебирать в результирующем только для чтения моды:
Dim db as DAO.Database
Dim rs as DAO.RecordSet
Set db = CurrentDB()
Set rs = db.OpenRecordSet("...", dbOpenForwardOnly)
If Not (rs Is Nothing) Then
With rs
Do While Not .EOF
' Do stuff '
.MoveNext
Loop
.Close
End With
Set rs = Nothing
End If
Set db = Nothing
Если мне не нужно перебирать записи, но просто проверить, если что-то было возвращено:
Set rs = db.OpenRecordSet("...", dbOpenForwardOnly)
If Not (rs Is Nothing) Then
With rs
If .RecordCount > 0 Then
' We have a result '
Else
' Empty resultset '
End If
.Close
End With
Set rs = Nothing
End If
Set db = Nothing
Это довольно оборонительно, и вам приходится приспосабливаться к вашим обстоятельствам, но он работает правильно каждый раз.
Что касается вашего 2 вопроса, тестирование (BOF
Или EOF
) после открытия записей должны быть более надежными, чем версия And
, хотя я бы использовать Recordcount
сам.
Редактировать после вашего пересмотренного вопроса:
Из кусочка коды вы добавили на ваш вопрос, я вижу несколько вопросов, главный из которых, что ваш SQL заявление отсутствует и ORDER BY
положения.
Проблема заключается в том, что вы ожидаете, что набор результатов будет в Begin Order
, а затем в последовательности End Order
, но ваш SQL-запрос не гарантирует этого.
В большинстве случаев, так как вы используете автоинкрементный как ID, ядро базы данных будет возвращать данные в этом естественном порядке, но нет никакой гарантии, что:
- Это всегда будет происходить таким образом
- Что исходные данные были сохранены в ожидаемой последовательности, что привело к идентификаторам, которые находятся в «неправильном» порядке.
Итак, всякий раз, когда у вас есть ожидания относительно последовательности набора результатов, вы должны явно заказать его.
Я хотел бы также реорганизовать этот бит кода:
' ids are autoincrement long integers '
SQLString = "select * from Orders where type = OrderBegin or type = OrderEnd"
Dim OrderOpen as Boolean
OrderOpen = False
Set rs = db.Openrecordset(SQLString)
If rs.bof <> True And rs.eof <> True Then
myrec.movelast
If rs.fields("type").value = BeginOrder Then
OrderOpen = True
End If
End If
В отдельную функцию аналогично:
' Returns true if the given CustID has a Open Order, '
' false if they are all closed.'
Public Function IsOrderOpen(CustID as Long) As Boolean
Dim result as Boolean
result = False
Dim sql as String
' Here I assume that the Orders table has a OrderDateTime field that '
' allows us to sort the order in the proper chronological sequence '
' To avoid loading the complete recordset, we sort the results in a way '
' that will return the last used order type as the first record.'
sql = sql & "SELECT Type "
sql = sql & "FROM Orders "
sql = sql & "WHERE ((type = OrderBegin) OR (type = OrderEnd)) "
sql = sql & " AND (CustID=" & CustID & ")"
sql = sql & "ORDER BY OrderDateTime DESC, Type DESC;"
Dim db as DAO.Database
Dim rs as DAO.Recordset
Set db = CurrentDB()
Set rs = db.Openrecordset(sql, dbOpenForwardOnly)
If Not (rs Is Nothing) Then
If rs.RecordCount > 0 Then
result = (rs!type = BeginOrder)
End If
rs.Close
End If
Set rs = Nothing
Set db = Nothing
IsOrderOpen = result
End Function
Это сделало бы все это немного более надежным.
Что находится в вашем SQLSTRING? – NotMe
Это просто простой выбор на одной таблице, который в случае неудачи сделал/должен был вернуть около десятка записей. – jjb
«один из bof/eof be true» - вы имеете в виду xor («побитное сравнение двух выражений с использованием эксклюзивного или логического»), то есть одно верно, а другое - false? – onedaywhen