与直接在Access中查询OleDb时的结果不同

时间:2013-08-20 14:13:40

标签: .net vb.net ms-access ado.net oledb

我们目前在几个内部产品中使用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值的相同查询时,一切似乎都没问题。某些Text字段中的特定值是否可能导致OleDB忽略该特定情况下的行?没有错误消息,代码运行成功,只有错误的结果。

在Google和StackOverflow上搜索此问题几乎没有提供帮助,因为我找到的唯一解决方案是LIKE语句的问题(使用%而不是*)和参数名称冲突,这些都不相关我的情况。

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

编辑&amp;溶液

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

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分: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))