MS Access中SQL查询的奇怪结果

时间:2009-07-15 19:03:28

标签: sql ms-access

好的,这是我正在运行的MS Access数据库中的一个奇数。

我有一个SQL查询:

SELECT * 
FROM [Service Schedule]
WHERE ID=2 
  AND Volume <= 3000 
  AND Term='Monthly'
  AND special = 'Regular'
ORDER BY volume

当我将它放入查询构建器的SQL视图中时,我得到2条记录,一条卷的体积为0,另一条卷的卷为3000.

当我使用此代码时:

sSQL = "SELECT * FROM [Service Schedule] WHERE ID=2 AND Volume <= 3000 AND Term='Monthly' and special = 'Regular' ORDER BY volume"            
Set rsServiceSched = CurrentDb.OpenRecordset(sSQL, dbOpenDynaset, dbSeeChanges)

**要查看代码中查询的内容,我使用Debug.Print输出记录数和卷。

我只获得1条记录,即音量为0的记录。

这里真的很奇怪......

当我将Volume&lt; = 3000更改为Volume&lt; 3000我得到一条记录(音量= 0)

当我将Volume&lt; = 3000更改为Volume = 3000时,我得到一条记录(volume = 3000)

有人发现我正在做的事情明显错误吗?

5 个答案:

答案 0 :(得分:4)

Digression:关于DAO记录集记录计数的讨论

在.MoveLast之后,DAO记录集的记录数量不能保证准确,但如果记录集返回任何记录,则.RecordCount将为1或更多。

请注意,表类型记录集将立即返回准确的.RecordCount,而不返回.MoveLast,但请记住,您无法在链接表上打开表类型记录集。另外,小心并且不要假设您正在获得所需的记录集类型,除非您明确指定它。虽然dbOpenTable是默认记录集类型,但如果表或SQL字符串无法作为表类型记录集打开,则它将打开动态集。因此,你可以认为你正在打开一个表类型的记录集,因为table-type是默认的,你传递了一个表名:

  Set rs = CurrentDB.OpenRecordset("MyTable")

但是你必须记住,只是因为你传递了一个表,它不一定会打开一个表类型的记录集,并且recordcount不一定是准确的。如果您确实想确定要打开表类型记录集,则需要明确指定:

  Set rs = CurrentDB.OpenRecordset("MyTable", dbOpenTable)

如果“MyTable”是链接表,则会抛出错误。如果您混合使用链接表和本地表,则必须使用两种不同的方法来获取表类型记录集。否则(即,如果你没有指定记录集类型并在可能的情况下让它成为表类型,而在没有指定时使用动态集),你需要知道何时需要.MoveLast来获得准确的.RecordCount。如果你真的想在这种情况下有效率,你将测试记录集的.Type:

  Set rs = CurrentDB.OpenRecordset("MyTable")
  If rs.Type = dbOpenDynaset Then
     rs.MoveLast
  End If

此时,无论记录集是以表格类型还是作为动态集打开,您都将获得准确的.RecordCount属性。

但请记住,您很少需要使用完整记录集来获取记录数。通常,您只会检查.RecordCount,以查看您的记录集是否已返回任何记录,在这种情况下,您不需要准确的计数。

同样,如果你要浏览完整的记录集,你最终会有一个准确的RecordCount。也就是说,做到这一点毫无意义:

  Set rs = CurrentDB.OpenRecordset("MyTable")
  rs.MoveLast
  If rs.RecordCount > 0 Then
     .MoveFirst
     Do Until rs.EOF
       [something or other]
       .MoveNext
     Loop
  End If
  Debug.Print rs.RecordCount

.MoveLast在该上下文中完全不需要,因为您不需要知道代码中该点的确切计数。

另外,请记住,在某些情况下,您确实需要知道确切的.RecordCount,使用内置的Access DCount()函数可能更有效,或者执行以下操作:< / p>

  Dim lngRecordCount As Long
  lngRecordCount = CurrentDB.OpenRecordset("SELECT COUNT(*) FROM MyTable")(0)

或者:

  lngRecordCount = DBEngine.OpenDatabase(Mid(CurrentDB.TableDefs("MyTable").Connect, 11)).TableDefs("MyTable").RecordCount

有各种有效的快捷方式可以在不强制记录集指针前往最后一条记录的情况下获得准确的RecordCount。

BTW,纯表类型记录的RecordCount准确的原因之一是因为它不需要计算 - Jet / ACE将RecordCount属性作为其常规操作的一部分。

Digression:讨论ADO记录集的记录数

来自@onedaywhen

对于ADO记录集,RecordCount属性将始终为最终值。也就是说,与DAO不同,如果检查其值,则无法随后更改。导航EOF不会以任何方式影响ADO的RecordCount值。

即使异步提取记录(DAO记录集没有明确支持)也是如此:即使记录集尚未满,RecordCount属性仍然反映最终值(不是到目前为止提取的记录,如DAO)。

CursorLocationCursorType的某些组合会导致RecordCount始终为-1,这意味着不支持该属性。但是,再次,这将保持不变,即如果它最初为-1,那么它将始终为-1。

不支持RecordCount的Access数据库引擎的适用组合是adOpenForwardOnlyadOpenDynamic,但仅限于使用服务器端游标位置时。 (注意Access数据库引擎实际上不支持动态游标:而是adOpenDynamic重载,以便用户向引擎提供记录集的Source是动态SQL代码的优化'提示'。< / p>

请注意,设置记录集的Filter属性会更改RecordCount以反映应用过滤器后的记录数。

答案 1 :(得分:1)

我不确定你对那张桌子的PK值做了什么,但当你说:“ID = 2”对我来说听起来很可疑,因为我总是使用代理键(从不自然)而且ID总是PK 。由于您没有加入任何表,这告诉我您应该总是期望结果中有一行/元组。

如果ID不是您的PK,您是否介意通过评论告诉我?

也许您需要使用以下方法迭代结果集: Set.MoveNext

答案 2 :(得分:1)

听起来你希望“看到”所有记录,但我认为你只是在检索第一条记录。我这样说是因为你看到每个案例的第一条记录是什么。您可能需要移动到记录集中的下一条记录才能看到下一条记录。

rsServiceSched.MoveNext

答案 3 :(得分:0)

您可能没有遍历结果集。 rsServiceSched仅指向第一个记录,该记录将是具有最低音量的记录(您的order by子句的bacuase)。现在你需要做一些事情,然后前进到下一个记录

This example可能会帮助你...

答案 4 :(得分:-2)

这是DAO,你需要移动以获得完整的记录数;否则,如果记录存在,你只会获得1,如果不存在,你将获得0。