我是C ++程序员,我不熟悉.NET数据库模型。我通常使用IDataReader
(OdbcDataReader
,OledbDataReader
或SqlDataReader
)来读取数据库中的数据。有时当我需要大量数据时,我使用DataAdapter
,但是我应该怎么做才能实现存在于ODBC等本机库中的可滚动游标的功能?
我必须编写一个程序,作为客户端程序和MSSQL之间的代理,对于这个库,我有以下要求:
LIMIT OFFSET
,遗憾的是MSSQL
不支持它,ROW_NUMBER
中不存在MSSQL2000
如果它支持,那么我再次需要了解程序逻辑,并且需要解析SQL命令(实际上我用boost::spirit
编写了一个解析库,但这是本机代码,除此之外我还不是100%肯定它的功能)。MSSQL
将专用于我的程序,所以我真的想利用服务器和DBMS的所有功能来实现我的功能。现在:
答案 0 :(得分:3)
在SQL Server中,您可以创建分页的查询。您可以从应用程序轻松处理的页码。您无需为此任务创建游标。
对于SQL Server 2005更高
SELECT * FROM ( SELECT *, ROW_NUMBER() OVER (ORDER BY ID) AS ROW FROM TABLEA ) AS ALIAS
WHERE ROW > 40
AND ROW <= 49
对于SQL Server 2000
SELECT TOP 10 T.* FROM TABLA AS T WHERE T.ID NOT IN
( SELECT TOP 39 id from tabla order by id desc )
ORDER BY T.ID DESC
PD:已编辑为包含对SQL Server 2000的支持
答案 1 :(得分:2)
我通常使用DataReader.Read()
来跳过在不支持分页的数据库上进行分页时我不想使用的所有行。
如果您不想自己构建SQL分页查询,可以自由使用我的分页类:https://github.com/jgauffin/Griffin.Data/blob/master/src/Griffin.Data/BasicLayer/Paging/SqlServerPager.cs
答案 2 :(得分:2)
当Microsoft设计ADO.NET API时,他们决定只公开firehose游标(IDataReader
等)。这可能会或可能不会对您造成问题。你说你想要“可滚动游标的功能”,但这可能意味着各种各样的事情,而不仅仅是分页,每个特定的用例都可以通过各种方式解决。例如:
要求:用户应该可以随意向上和向下翻页结果。
ROW_NUMBER()
函数。这比滚动光标更有效。要求:我有一个非常大的数据集,我只想一次处理一行,以避免内存不足。
要求:我正在进行一项复杂的计算,涉及在结果集中向前和向后移动。
更新(问题中提供了更多信息)
您的业务要求太多了。您必须处理假定存在可滚动游标的任意查询,但您不能提供可滚动游标,并且您不能重写客户端代码以不使用可滚动游标。这是一个不可能的位置。我建议你坚持你现在拥有的东西(C ++和ODBC),不要试图在.NET中重写它。
答案 3 :(得分:2)
我不认为游标会为你的特定情况而工作。主要原因是你有3层。但是,让我们退两步。
大多数3层应用程序都有无状态中间层(您的c ++代码)。缓存很好,因为它实际上只是一个优化,并没有在中间层创建任何真实状态。中间层通常具有少量到数据库的打开会话。因为打开db会话对于处理器而言是昂贵的,并且在db会话打开之后,在数据库服务器上保留一定量的RAM。当中间层收到请求时,将处理该请求并将其传递给SQL数据库。可以使用算法来挑选任何打开的会话,或者甚至可以随机地完成。在此模型中,无法知道哪个会话将接收下一个请求。游标属于收到原始查询请求的会话。所以你真的不希望接收会话是那个打开游标的会话。
我描述的3层模型主要用于Web应用程序,因此可以扩展到数百或数千个客户端。如果SQL服务器永远无法打开那么多会话。 Microsoft ADO.NET已经有许多功能来支持我所描述的架构,因此实现起来并不是很难。根据具体情况,即使在非Web应用程序中也是如此。您可以跟踪您的会话,以便您可以为每个客户端打开一个会话,我首先要确保用例证明这一点。知道开放游标也可以占用大量资源。
游标仍然在单个事务中占有一席之地,只是很难让它们保持打开状态,以便客户端应用程序可以获取/更新结果集中的值。
我建议您在查询事务中执行以下操作。在单独的表中存储查询中主表的主键值。在单独的表上包括其他值,如sessionid和rownumber。通过链接到原始查询中的新表返回一些第一行。在后续调用中,只需链接到新表即可再次查询相应的行。您将需要等效的缓存机制来清除旧数据,并根据您的需要刷新结果集。