I'm posting a fuller response to wrap this up and for the benefit of anyone else coming across this...
There are a couple of ways you can get a "row number" in this instance, but unfortunately you are constrained by a feature of SQL where
Quote:
Windowed functions can only appear in the SELECT or ORDER BY clauses.
Which means you can't do something like this:
SELECT Country, CountryCode
FROM Country
WHERE ROW_NUMBER() OVER (ORDER BY CountryCode) > 4
To overcome the issue you could use a Common Table expression, or for more flexibility a temporary table or a table variable e.g.
CREATE PROCEDURE [dbo].[SP3]
@param int
AS
BEGIN
SET NOCOUNT ON;
DECLARE @T TABLE (rn INT, Country varchar(30), CountryCode int)
INSERT INTO @T
SELECT ROW_NUMBER() OVER (ORDER BY CountryCode), Country, CountryCode
FROM Country
SELECT TOP 5 Country, CountryCode from @T WHERE rn > @param
RETURN (SELECT MAX(rn) FROM @T WHERE rn > @param AND rn <= @param + 5)
END
GO
You could even have an identity column on that table variable and omit the ROW_NUMBER function altogether (although you will still need the ORDER BY) E.g.
CREATE PROCEDURE [dbo].[SP2]
@param int
AS
BEGIN
SET NOCOUNT ON;
DECLARE @T TABLE (rn INT IDENTITY(1,1), Country varchar(30), CountryCode int)
INSERT INTO @T
SELECT Country, CountryCode
FROM Country
ORDER BY Country
SELECT TOP 5 Country, CountryCode from @T WHERE rn > @param
RETURN (SELECT MAX(rn) FROM @T WHERE rn > @param AND rn <= @param + 5)
END
GO
You can then call the Stored Procedure like this:
DECLARE @nextValue int = 0
EXEC @nextValue = dbo.SP2 @nextValue
exec @nextValue = dbo.SP2 @nextValue
EXEC @nextValue = dbo.SP2 @nextValue
exec @nextValue = dbo.SP2 @nextValue
For my data (see below) I get queries returning 5 records, 5 records, 4 records then 0 records.
Incidentally that is why I used the
WHERE rn > @param AND rn <= @param + 5
for the RETURN value from both my SPs ... the number of records may not divide exactly by 5 (or whatever number you choose). If other users are adding data to the table when you are running these queries you want to make sure you don't accidentally miss any rows by using
RETURN @param + 5
For completeness here is the data I used to test these examples:
CREATE TABLE [dbo].[Country](
[id] [int] NULL,
[Country] [varchar](30) NULL,
[CountryCode] [int] NULL,
[RatePerMin] [decimal](15, 2) NULL
) ON [PRIMARY]
INSERT INTO Country VALUES
(248,'Nepal' ,97 ,3.20),
(1, 'Afghanistan' ,93 ,4.00),
(2, 'Albania' ,355 ,3.50),
(3, 'Algeria' ,213 ,2.20),
(4, 'American Samoa' ,1684,2.00),
(5, 'Andorra' ,376 ,4.20),
(6, 'Angola' ,244 ,4.20),
(7, 'Anguilla' ,1264,4.50),
(8, 'Antarctica/Norfolk Island',672 ,5.00),
(9, 'Antigua and Barbuda' ,1268,4.50),
(10, 'Sudan' ,249 ,1.40),
(11, 'Qatar' ,974 ,1.50),
(12, 'Egypt' ,20 , 1.60),
(13, 'Sri Lanka' ,94 , 1.70)
Note that if you want to make the number of rows that you are extracting on each call one of the parameters to the stored procedure then you will have to generate the SQL query dynamically within the body of the SP - this article explains how
Building Dynamic SQL In a Stored Procedure[
^]