我正在编写一个正在搜索Access 2010数据库的vb.net应用程序,并遇到了一个我似乎无法解决的问题。以下代码段是问题。
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]=@p1 AND [Valve Size]=@p2 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
当我使用一组特定值直接在Access中运行SQL语句时,我得到了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是正确的。
答案 0 :(得分: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 CageType=@p1 AND ValveSize=@p2 AND Height BETWEEN @p3 AND @p4"
Dim sql2 = "SELECT * FROM Cage WHERE ValveSize=@p2 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
结果:
我认为您的数据或数据类型有些奇怪。列出了2个仅用于测试的SQL语句,并减少了所需的测试数据量。 "SELECT * FROM Cage WHERE ValveSize=@p2 AND Height > @p3 AND Height <= @p4"
会返回相同的结果。
请注意OleDBConnection
和OleDbCommand
之类的内容会分配资源,并且应该在完成后处理。 Using
语句为我们做了这个。我还使用了Add
而不是AddWithValue
,因此可以指定数据类型,让VB / OleDB无法猜测最新情况。此外,不需要临时适配器或DataSet
- 您可以使用DataTable
直接填充DataReader
。
另请注意,OleDb
不使用命名参数 - 它们只是位置占位符。使用OleDb
,您必须 Add
按照它们在SQL中出现的确切顺序。你的确如此,但这解释了为什么上面的代码只能注释掉@p1
参数并仍然有用。
<强>后记强>
正如在某些时候可能会删除的评论中所述,真正的问题是OleDbCommand
正在被重复使用。因此,它可能具有从上次遗留的参数或值。这意味着发布的代码不是导致问题的真实代码。
DbCommand
个对象是特定于查询的,因为它们可能包含的参数是每次使用Using
块时创建,使用和处理它们的另一个原因。
另见:
(这些是博客 - 某些有名望的人的有趣意见 - 而不是用石头雕刻的宙斯之词)
答案 1 :(得分:0)
我认为这是一些时髦的OleDb-ness。在这些情况下,你也可以只是明确:
SELECT *
FROM [CAGE - BARREL]
WHERE [Type] = @p1
AND [Valve Size] = @p2
AND [Cage Height] >= @p3
AND [Cage Height] <= @p4