与直接在 Access 中查询相比,使用 OleDb 查询时的结果不同

Posted

技术标签:

【中文标题】与直接在 Access 中查询相比,使用 OleDb 查询时的结果不同【英文标题】:Different results when querying with OleDb compared to directly in Access 【发布时间】:2013-08-20 14:13:40 【问题描述】:

我们目前在几个内部产品中使用 ADO.Net,其中一个产品必须使用 OleDB 查询 Microsoft Access 数据库。我们现在遇到的问题是,当OleDbDataAdapter.Fill 执行和直接在 Microsoft Access 的 SQL 视图中执行时,其中一个查询不会产生相同的结果。

查询如下所示:

SELECT DISTINCT t1.* 
FROM tableOne AS t1 
INNER JOIN tableTwo AS t2 ON t2.tableOne_no = t1.tableOne_no 
WHERE t1.status = 'A' 
AND t2.tableThree_no = @p_tableThree_no
AND t2.status = 1 
AND (t2.startDate IS NULL OR (YEAR(t2.startDate) <= @p_year AND MONTH(t2.startDate) <= @p_month)) 
AND (t2.endDate IS NULL OR (YEAR(t2.endDate) >= @p_year AND MONTH(t2.endDate) >= @p_month))

我们使用以下代码查询数据库,使用 Microsoft ACE OLEDB 12 和 ADO.Net:

Dim oDataSet As New DataSet()
    
Using oSqlConnection As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=\\NetworkDrive\database.mdb;User Id=admin;Password=password;")

    Using oSqlCommand As New OleDbCommand(p_sQuery, oSqlConnection)

        oSqlCommand.Parameters.AddWithValue("@p_tableThree_no", 1111)
        oSqlCommand.Parameters.AddWithValue("@p_year", 2013)
        oSqlCommand.Parameters.AddWithValue("@p_month", 7)
        oSqlCommand.CommandType = CommandType.Text

        Using oDataAdapter As New OleDbDataAdapter()

            oDataAdapter.SelectCommand = oSqlCommand

            oSqlConnection.Open()
            oDataAdapter.Fill(oDataSet)

        End Using

    End Using

End Using

不知何故,从 OleDB 执行查询所提供的结果数量与在 Microsoft Access 中执行相同的查询不同(Access 具有正确数量的结果)。当使用不同的@p_tableThree_no 值执行相同的查询时,一切似乎都很好。是否有可能来自某些文本字段的特定值会导致 OleDB 在特定情况下忽略行?没有错误信息,代码运行成功,只有错误的结果。

在 Google 和 *** 上搜索此问题几乎没有帮助,因为我发现的唯一解决方案是针对 LIKE 语句(使用 % 而不是 *)和参数名称冲突的问题,这与我的无关情况。

我错过了什么吗?查询对于 OleDB 来说是否太复杂?我应该用括号括起来吗?我不知道我做错了什么。

编辑和解决方案

原来这个查询一开始就错了,而且没有人(包括我自己)第一眼就发现了它。当我注意到 MONTH(t2.startDate) &lt;= @p_month 如果日期是例如 2012-11 而不是 2013-07 时,我正在重写来自 stratch 的查询。我仍然不知道为什么直接在 Access 中执行并在弹出窗口中提供参数时查询结果“错误正确”,但这是我不愿意解决的另一个谜团。我接受了@HansUp 的回答,因为他确实向我提供了一个双方都相同的查询,而且他是让我对 SQL 本身产生怀疑的人。

【问题讨论】:

tableThree_no的数据类型是什么? tableThree_no 字段是 Access 中的 Number (Long Integer) 类型。该参数是 .Net 中的整数类型。针对特定情况传递的值完全符合整数的“限制”,并且来自之前在 .Net 应用程序中检索到的另一个数字(长整数)字段。 【参考方案1】:

在 SQL 语句中定义参数,然后像以前一样从代码中提供值。

不要担心Parameters.AddWithValue 中的参数名称。 OleDb 忽略参数名称......你可以做.AddWithValue("Hello World!", 1111),它不会改变任何东西。但是,您必须按照 Access 期望的顺序提供参数,我希望添加 PARAMETERS 子句可以避免混淆。

PARAMETERS
    p_tableThree_no Long,
    p_year Long,
    p_month Long;
SELECT DISTINCT t1.* 
FROM
    tableOne AS t1 
    INNER JOIN
    tableTwo AS t2
    ON t2.tableOne_no = t1.tableOne_no 
WHERE
        t1.status = 'A' 
    AND t2.tableThree_no = p_tableThree_no
    AND t2.status = 1 
    AND (t2.startDate IS NULL
         OR (YEAR(t2.startDate) <= p_year AND MONTH(t2.startDate) <= p_month)) 
    AND (t2.endDate IS NULL
         OR (YEAR(t2.endDate) >= p_year AND MONTH(t2.endDate) >= p_month))

【讨论】:

令人惊讶的是,在 Access 中直接执行时,添加PARAMETERS 子句会导致查询产生错误的结果(与 OleDB 相同)。 该查询使用 OleDb 给出的结果与直接在 Access 中运行时的结果相同。现在你得到了相同的结果,你的问题已经转移到“但这不是我想要的结果”。这和你问的问题不同。我鼓励您将该问题作为一个新问题提出。 感谢您的帮助,但是在没有参数定义的情况下直接在Access中执行查询时,Access会在弹出窗口中询问参数值(无论是命名还是?)和结果是正确的。引入PARAMETERS 子句让他们错了。我的问题更多是关于“如何使 OleDB 产生与 Access 相同的结果,因为 Access 具有正确的结果”。 您现在有一个 Access 查询,它在 Access 和 OleDb 中产生相同的结果。现在修改 Access 查询,保留 PARAMETERS 子句,直到它在 Access 中返回您想要的结果。当您到达该点时,相同的查询将返回与 OleDb 相同的结果。 除非证明 OleDB 自动在其执行的查询中包含 PARAMETERS 子句,否则我无法确定添加该子句并重构查询以使其直接在 Access 中工作会使其在 OleDB 中工作. OleDB可能在其查询中添加PARAMETERS 子句这一事实可能是开始的问题/解决方案。【参考方案2】:

ACE.OLEDB 忽略参数名称,因此 OleDb 查询可能会变得混乱,因为 @p_year@p_month 参数在 SQL 命令中重复但它们仅在 OleDbCommand.Parameters 集合中指定一次。我倾向于尝试使用? 作为参数占位符并重复最后两个参数(即,使用五个AddWithValue 语句而不是三个)。

【讨论】:

我尝试了您的建议,但似乎无法解决问题。我将查询更改为仅使用? 参数,并将AddWithValue 复制为p_yearp_month。我的查询中有 5 个?,我添加了 5 个参数,例如,oSqlCommand.Parameters.AddWithValue("", 2013)

以上是关于与直接在 Access 中查询相比,使用 OleDb 查询时的结果不同的主要内容,如果未能解决你的问题,请参考以下文章

在 Ms Access 查询中插入换行符

api 与直接查询数据库相比如何

Oracle Forms 作为“前端”与 Microsoft Access 相比如何?

与 SQL 相比,Hibernate JPQL 查询非常慢

access 不能建立删除查询。

插入数十万行时,MySQL 与 MS Access 相比非常慢