1

我们目前在几个内部产品中使用 ADO.Net,其中一个产品必须使用 OleDB 查询 Microsoft Access 数据库。我们现在遇到的问题是,其中一个查询在由OleDbDataAdapter.FillMicrosoft Access 的 SQL 视图执行时和直接在 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 和 StackOverflow 上搜索这个问题几乎没有帮助,因为我发现的唯一解决方案是LIKE语句问题(使用 % 而不是 *)和参数名称冲突,这与我的情况无关。

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

编辑和解决方案

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

4

2 回答 2

0

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

于 2013-08-20T15:36:00.673 回答
0

在 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))
于 2013-08-20T16:01:58.473 回答