3

我有一个要求,我需要提取数据结果集的前 100 个,以及满足我的过滤条件的总数据的记录数。

谢谢,马诺伊。

4

3 回答 3

3

您可以使用输出参数来返回记录总数,也可以使用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");
}

此方法只是向您展示如何拨打电话的示例。不要这样写生产代码!!!

于 2017-03-17T09:55:34.960 回答
1

需要对结果进行分页的情况并不少见,同时还要显示可能的结果页面总数,并且这里可能已经有很多关于此的问题。不幸的是,没有内置的机制来处理这个问题。这让您只有几个选择:

  1. 运行查询两次:一次获取总行数,然后再次获取所需结果的子集/页面。这里的缺点是你运行它两次。(这是@A2H答案的基础)

  2. 运行一次查询,将结果转储到本地临时表中,并使用@@ROWCOUNT. 然后,从临时表中选择所需的结果子集/页面。这里的缺点是您会受到 IO(tempdb 数据文件和事务日志)的影响,尽管使用内存中 OLTP 可能会改善这一点。(类似于@granadaCoder 的答案,但该答案并未遵循行要求的子集)

  3. 将其构建到应用程序代码中:

    • 声明一个计数器来跟踪总行数
    • 运行完整的查询
    • 调用SqlDataReader.Read()(假设您使用的是 .NET)——无需实际检索任何数据——获取要跳过的行数,然后读取所需结果子集/页面的行,最后SqlDataReader.Read()再次调用——没有实际检索任何数据 - 直到没有什么可读取的。在 3 个部分的每一个中增加行计数器。

    请在 StackOverflow 上查看我的以下答案,该答案提供了有关此方法的更多详细信息(和变体):

    TSQL:有没有办法限制返回的行并计算在没有限制的情况下返回的总数(不将其添加到每一行)?

于 2017-03-17T16:42:33.490 回答
1

我的答案之一与 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'
于 2017-03-17T12:52:52.960 回答