Что, если инструкция SQL не находит никаких «совпадений» в таблице?

#sql #ms-access #vbscript

#sql #ms-access #vbscript

Вопрос:

Используя MS Access, я попытался запустить инструкцию SQL, но я не могу заставить ее работать в случае, если в таблице еще нет записей. Буду признателен за помощь! Спасибо!

 Public Function GetReferenceID(RefCode As String) As Integer
    Dim RefID As Integer
    Dim rec As Recordset

    Call connectDB
    sSQL = "select RefID from Exceptions where RefCode = '" amp; RefCode amp; "'"
    Set rec = CurrentDb.OpenRecordset(sSQL)

    If (Not rec.EOF And Not rec.BOF) Then
        RefID = rec.RecordCount   1
    Else
        RefID = 1
    End If
    GetReferenceID = RefID 
End Function

Private Sub RefCode_Change()
    Dim tr As Transactions, rID As Integer
    Set tr = New Transactions
    tr.GetReferenceID (RefCode.Value)
end sub
  

ОБНОВЛЕНИЕ! В этой строке ошибка (ошибка времени выполнения 3464, «Несоответствие типа данных в выражении критериев«):

 Set rec = CurrentDb.OpenRecordset(sSQL)
  

…в этом коде:

 Private Sub RefCode_Change()
        Dim rec As Recordset, RefID As Integer
        sSQL = "select RefID from Exceptions where RefCode = '" amp; RefCode.Value amp; "'"
        Set rec = CurrentDb.OpenRecordset(sSQL)

        If (rec.EOF And rec.BOF) Then
            RefID = 1
        Else
            rec.MoveFirst
            RefID = rec.RecordCount   1
        End If
End Sub
  

Комментарии:

1. Используйте параметризованный SQL, чтобы избежать атак с использованием SQL-инъекций. Что, если кто-нибудь отправит вам рефкод «‘;исключения из таблицы удаления;—«?

2. Если кто-то отправит ему рефкод «‘;исключения из таблицы удаления;», Access’ database engine не выполнит удаление таблицы.

3. @HansUp: попробуйте это: Используйте параметризованный SQL, чтобы избежать ошибок (например, при повторном коде. Значение содержит одинарную кавычку) и чтобы избежать внедрения WHERE предложения SQL в Access (например, что, если кто-то отправит вам рефкод ' OR '' = ' — ?

4. @Ali: вы, кажется, предполагаете, что RefID будет идеальной последовательностью, т. Е. что MAX (RefID) = COUNT (*), MIN (RefID) = 1, без пробелов и т.д. Держу пари, у вас нет ограничений на эту таблицу, чтобы гарантировать, что ваши предположения всегда будут верны. Но вместо того, чтобы добавлять эти ограничения, я настоятельно рекомендую вам вместо этого использовать другой подход к генерации идентификаторов.

5. @onedaywhen Просто для ясности, я не спорил с параметрами. Моя точка зрения заключалась просто в том, что «; отбросьте трабл … » не представляет опасности для ядра базы данных Access.

Ответ №1:

Я думаю, вы хотите это сделать…

 If (rec.EOF And rec.BOF) Then
    'empty recordset
    RefID = 1
Else
    'at least one row
     rec.movefirst
     RefID = rec.RecordCount   1
End If
  

Вы также могли бы упростить все это до

 RefID = Dcount("*","Exceptions","refCode='" amp; RefCode amp; "'")  1
  

Комментарии:

1. Refcode — это строковое поле. Вы знаете, как я должен это исправить?

Ответ №2:

Я не совсем уверен, в чем проблема, но я вижу две потенциальные проблемы:

  1. вы не указали объявление вашего набора записей, поэтому вы можете столкнуться с неоднозначностью между типами наборов записей DAO и ADO. Вместо этого объявите свою переменную набора записей как Dim rs As DAO.Recordset или Dim rs As ADOX.Recordset (я думаю, что последнее правильно — я никогда не использую ADO, поэтому никогда не нужно указывать это!). Тот факт, что Set rec = CurrentDb.OpenRecordset(sSQL) возвращает несоответствие типов данных, убедительно наводит меня на мысль, что вы объявили набор записей ADO, потому что это вызвало бы несоответствие с набором записей DAO, возвращаемым CurrentDb.OpenRecordset().

  2. Наборы записей DAO не могут гарантированно возвращать точное количество записей, пока вы не пройдете весь набор записей. Благодаря технологии Rushmore от Jet / ACE начало набора записей доставляется, в то время как его конец все еще извлекается. Вы могли бы подождать некоторое время и надеяться, что количество записей точное, или вы можете явно создать rs.MoveLast, и в этом случае количество записей будет гарантированно точным.