我有一个要求,我需要提取数据结果集的前 100 个,以及满足我的过滤条件的总数据的记录数。
谢谢,马诺伊。
您可以使用输出参数来返回记录总数,也可以使用select
返回结果集的语句。
例如:
create procedure test
@totalCount int output
as begin
select * from something -- your select statement goes here
select @totalCount = 'write your statement that counts the records.'
end
如果您需要从代码中调用它,这里有一个Java
示例来说明如何进行调用:
public void test(Connection con) throws SQLException{
CallableStatement cs = con.prepareCall("test");
//you can set more parameters if you need to, i.e.: cs.setInt(0,id);
//you need to register your output parameter. If you are referencing it by name, it should match with the name given in the stored procedure.
cs.registerOutputParameter("totalCount", Types.INTEGER);
ResultSet rs = cs.executeQuery();
while(rs.next()){
//you can save the data into a data structure; a list for example.
//Or just print the records.
}
//here's how you can get the total count
int total = cs.getInt("totalCount");
}
此方法只是向您展示如何拨打电话的示例。不要这样写生产代码!!!
需要对结果进行分页的情况并不少见,同时还要显示可能的结果页面总数,并且这里可能已经有很多关于此的问题。不幸的是,没有内置的机制来处理这个问题。这让您只有几个选择:
运行查询两次:一次获取总行数,然后再次获取所需结果的子集/页面。这里的缺点是你运行它两次。(这是@A2H答案的基础)
运行一次查询,将结果转储到本地临时表中,并使用@@ROWCOUNT
. 然后,从临时表中选择所需的结果子集/页面。这里的缺点是您会受到 IO(tempdb 数据文件和事务日志)的影响,尽管使用内存中 OLTP 可能会改善这一点。(类似于@granadaCoder 的答案,但该答案并未遵循行要求的子集)
将其构建到应用程序代码中:
SqlDataReader.Read()
(假设您使用的是 .NET)——无需实际检索任何数据——获取要跳过的行数,然后读取所需结果子集/页面的行,最后SqlDataReader.Read()
再次调用——没有实际检索任何数据 - 直到没有什么可读取的。在 3 个部分的每一个中增加行计数器。 请在 StackOverflow 上查看我的以下答案,该答案提供了有关此方法的更多详细信息(和变体):
我的答案之一与 A2H 类似,但如果您的“计数”与您的选择查询直接相关,则可以避免“双击”,但将结果放在 #temp 表中。
但是,您也可以使用@@ROWCOUNT 技巧。这是一个新的答案,恕我直言。
CREATE PROCEDURE dbo.SelectAndCountExample
@TotalCount int output
as
BEGIN
IF OBJECT_ID('tempdb..#Holder') IS NOT NULL
begin
drop table #Holder
end
CREATE TABLE #Holder
(SurrogateKey INT, SomeValue VARCHAR(64) )
/* simulate your insert */
INSERT INTO #HOLDER (SurrogateKey , SomeValue)
select 101 , 'A' union all select 102, 'B' union all select 103, 'C' union all select 104, 'D'
/* optional stuff */
/* CREATE CLUSTERED INDEX IDX_TempHolder_ID ON #Holder (ID) */
/* CREATE INDEX IDX_TempHolder_ID ON #Holder (ID) */
Select @TotalCount = count(*) From #Holder
Select SurrogateKey , SomeValue from #HOLDER
IF OBJECT_ID('tempdb..#Holder') IS NOT NULL
begin
drop table #Holder
end
END
GO
declare @MyVariable int
EXEC dbo.SelectAndCountExample @MyVariable output
Select @MyVariable as '@MyVariable Value'
GO
和
CREATE PROCEDURE dbo.SelectAndCountExampleUsingRowCount
@TotalCount int output
as
BEGIN
select 101 , 'A' union all select 102, 'B' union all select 103, 'C' union all select 104, 'D'
Select @TotalCount = @@ROWCOUNT
IF OBJECT_ID('tempdb..#Holder') IS NOT NULL
begin
drop table #Holder
end
END
GO
declare @MyVariable int
EXEC dbo.SelectAndCountExampleUsingRowCount @MyVariable output
Select @MyVariable as '@MyVariable Value'