2016-07-08 2 views
2

Я пишу приложение vb.net, которое ищет базу данных Access 2010 и столкнулось с проблемой, которую я не могу решить. Следующий сегмент кода - проблема.SQL BETWEEN Запрос, возвращающий неверные результаты

Using SQLcon 'public property containing OleDbConnection 
    Dim ds As New DataSet 
    Dim da As New OleDbDataAdapter 
    Dim cmd As New OleDbCommand 

    cmd.Connection = SQLcon 
    cmd.CommandType = CommandType.Text 

    Dim heightMin As Double = OverallHeight - 0.25 
    Dim heightMax As Double = OverallHeight + 0.125 

    cmd.CommandText = "SELECT * FROM [CAGE - BARREL] WHERE [Type][email protected] AND [Valve Size][email protected] AND [Cage Height] BETWEEN @p3 AND @p4" 
    cmd.Parameters.AddWithValue("@p1", CageType) '[Type] 
    cmd.Parameters.AddWithValue("@p2", ValveSize) '[Valve Size] 
    cmd.Parameters.AddWithValue("@p3", heightMin) '[Cage Height] 
    cmd.Parameters.AddWithValue("@p4", heightMax) '[Cage Height] 

    da = New OleDbDataAdapter(cmd) 
    SQLcon.Open() 
    da.Fill(ds, "[CAGE - BARREL]") 
    SQLcon.Close() 
End Using 

Когда я запускаю инструкцию SQL непосредственно в Access с определенным набором значений, я получаю 3 результата, как ожидалось. Когда я запускаю его через свою программу, я получаю 6, где 3 значения находятся за пределами моих границ для оператора BETWEEN. Я дважды проверял типы данных для поля в Access и переменные в vb.net. Я знаю, что чего-то не хватает. У кого-нибудь есть идеи, в которых я ошибаюсь?

ОБНОВЛЕНИЕ:

Значения в использовании заключаются в следующем.

@p1="INLET" 
@p2="10.50" 'this is a text field 
@p3=heightMin=6 'this is a number/double 
@p4=heightMax=6.375 'this is a number/double 

Значение, возвращаемое программа .net включает 5,5 и 3,688, которые находятся за пределами границ выше и 6, 6 и 6,188, которые являются правильными.

+1

Можете ли вы изменить свой вопрос, чтобы предоставить примеры значений, которые иллюстрируют проблему? Например, «Когда я указываю« ОбщийHeight »как ___, я получаю строки, содержащие значения [Cage Height] ___, которые находятся за пределами диапазона' heightMin' до 'heightMax'. –

+0

Работает ли это, если вместо использования' .AddWithValue' вы используете , например, 'cmd.Parameters.Add (новый OleDbParameter с {.ParameterName =" @ p3 ", .OleDbType = OleDbType.Double, .Value = heightMin})'? (И аналогично для других параметров.) –

+0

[Cage - Barrel] - это таблица – Mike

ответ

4

Я не могу воспроизвести проблему (либо). Тем не менее, я хотел бы использовать какую-либо форму >= AND <= вместо BETWEEN.

Тестовые данные:

Id CageType ValveSize Height 
1  A   XS  0.25 
2  A   S  0.51 
3  A   S2  0.55 
4  A   M  0.95 
5  A   L  1.26 
6  B   S  0.58 

Код:

Dim sql1 = "SELECT * FROM Cage WHERE [email protected] AND [email protected] AND Height BETWEEN @p3 AND @p4" 
Dim sql2 = "SELECT * FROM Cage WHERE [email protected] AND Height BETWEEN @p3 AND @p4" 

Dim t As String = "A" 
Dim v As String = "S" 
Dim minH As Double = 0.45 
Dim maxH As Double = 0.65 

Dim dt As New DataTable 
Using dbcon As New OleDbConnection(ACEConnStr) 
    Using cmd As New OleDbCommand(sql2, dbcon) 
     dbcon.Open() 

     ' only used with 'sql1': 
     'cmd.Parameters.Add("@p1", OleDbType.VarChar).Value = t 
     cmd.Parameters.Add("@p2", OleDbType.VarChar).Value = v 
     cmd.Parameters.Add("@p3", OleDbType.Double).Value = minH 
     cmd.Parameters.Add("@p4", OleDbType.Double).Value = maxH 

     dt.Load(cmd.ExecuteReader) 
     dgv1.DataSource = dt 
    End Using 
End Using 

Результат:

enter image description here

Я предполагаю, что есть что-то странное с вашими данными или типами данных. Есть два оператора SQL, перечисленные только для тестирования и уменьшающие объем требуемых данных теста. "SELECT * FROM Cage WHERE [email protected] AND Height > @p3 AND Height <= @p4" возвращает те же результаты.

Обратите внимание, что такие вещи, как OleDBConnection и OleDbCommand, выделяют ресурсы и должны быть утилизированы, когда вы закончите с ними. Заявление Using делает это для нас. Я также использовал Add, а не AddWithValue, чтобы указать тип данных, в результате чего VB/OleDB не имеет возможности угадать, что происходит. Кроме того, нет необходимости в адаптере temp или DataSet - вы можете заполнить DataTable непосредственно DataReader.

Следует также отметить, что OleDb не использует именованные параметры как таковые - они просто позиционные заполнители. С OleDb вы должныAdd их в том порядке, в каком они появляются в SQL. Твой, но это объясняет, почему приведенный выше код может просто прокомментировать параметр @p1 и по-прежнему работать.


Postscript

Как было отмечено в комментариях, которые могут в какой-то момент получить удалены, вопрос реального было то, что OleDbCommand в настоящее время resused. Таким образом, он может иметь параметры или значения, оставшиеся с последнего раза. Это означает, что код не является реальным кодом, вызывающим проблемы.

DbCommand Объекты являются такими конкретными запросами из-за параметров, которые могут включать в себя, что это еще одна причина для создания, использования и утилизации их для использования в качестве блока Using.


Смотрите также:

(эти блоги - интересные мнения отдельных людей некоторой репутацией - не Слово Зевса вырезанные в камне)

0

Я предполагаю, что это какая-то напуганная OleDb-ness. В этих ситуациях вы можете просто быть явным:

SELECT * 
FROM [CAGE - BARREL] 
WHERE [Type] = @p1 
    AND [Valve Size] = @p2 
    AND [Cage Height] >= @p3 
    AND [Cage Height] <= @p4 
+0

При использовании этого метода я получаю 0 записей, возвращенных из моей .net-программы. Он отлично работает в Access, хотя. Это неудобно. – Mike

+0

@Mike очень странный. Вы уверены, что это не проблема с типом данных? являются ли типы данных ваших параметров и каков тип данных столбца 'высота клетки '? – Brad

+0

Доступ - это тип Number, размер double, а переменные в моем коде - двойные. – Mike

Смежные вопросы