SQL Server程序设计可以在一次调用中获得结果和结果

时间:2017-03-17 09:45:46

标签: sql-server count multiple-results

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

谢谢, 的Manoj。

3 个答案:

答案 0 :(得分: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");
}

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

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

答案 2 :(得分:1)

在显示结果的可能页面总数的同时,需要翻阅结果并不常见,这里可能存在很多问题。不幸的是,没有内置的机制来处理这个问题。这让你只有几个选择:

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

  2. 运行一次查询,将结果转储到本地临时表中,并使用@@ROWCOUNT捕获进入临时表的行数。然后,从临时表中选择所需结果的子集/页面。这里的缺点是你正在点击IO(tempdb数据文件和事务日志),尽管可以通过使用内存中OLTP来改进。 (类似于@ granadaCoder的答案,但该答案并未跟进行子集的要求)

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

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

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

    TSQL: Is there a way to limit the rows returned and count the total that would have been returned without the limit (without adding it to every row)?