SQL Server pagination of a result set - sql-server

I have a very meaty stored procedure in a SQL Server 2000 DB which returns a single resultset. I don't want to (not allowed to) touch the original SP but would like add pagination to the returned records.
Is it possible to wrap this SP with another that takes the returned resultset and only gives me rows X to Y ?

create procedure ProcWrap
as
declare #T table (ID int, Name nvarchar(50))
insert into #T
exec ProcToWrap
select *
from #T
where ID < 10
Edit 1
Don't have SQL Server 2000 to test on and I don't remember if table variables where available then. Here is a procedure using a temp table instead. Added a RowNum identity column that you can use for pagination.
create procedure ProcWrap2
as
create table #T (RowNum int identity, ID int, Name nvarchar(50))
insert into #T
exec ProcToWrap
select *
from #T
where RowNum between 10 and 19
drop table #T
Edit 2
Output from ProcToWrap in this case is columns ID and Name. RowNum is generated automatically.

Get the results from the SP and put them in a temporary table, then you can select X results from that table.

As others have said you will have to put the results of the procedure in a temp table then select the rows you want from that.
To get a set of rows from your results you need to use the ROW_NUMER() function:
SELECT
ROW_NUMBER() OVER (ORDER BY ID) AS row_number, *
FROM
Your_Temp_Table
WHERE row_number BETWEEN 11 AND 20 -- For the second page of results with 10 per page.
EDIT: Just realised you are using SQL Server 2000 which does not have ROW_NUMBER(), sorry
EDIT2: Since you are storing the results of the query in a temp table you can add an incrementing integer field to that result set and use that as a simulation for the ROW_NUMBER() in order to select the row you need.
EDIT3: Here's a link to an article discussing pagination in SQL Server 2000

Related

Get first N records from stored procedure result set in SQL Server

Is there is any solution / query to get first N records from stored procedure result without retrieving the whole result set?
Consider my stored procedure returns 3 million rows, and I just want the first 10 rows from it.
The best approach would be to alter your stored procedure to be able to include a parameter for the TOP filter.
However, you could also use
SET ROWCOUNT 10
EXEC MyProc
Be careful to reset the value of ROWCOUNT afterwards otherwise you may impact other queries.
The downside is that you cannot control the order of the rows. I also haven't tested with such a large result set to identify whether this does reduce resource consumption enough.
You can use TOP clause to achieve it
Syntax
SELECT TOP number|percent column_name(s)
FROM table_name
WHERE condition;
Let's say that you have Your_stored_procedure return list of users
CREATE PROCEDURE Your_stored_procedure
AS
SELECT UserId, UserName
FROM yourtable
GO;
At here, you need to create temp table to store value from stored procedure
-- Check result
CREATE TABLE #TempTable
(
UserId INT,
UserName varchar(100),
)
INSERT INTO #TempTable(UserId, UserName)
EXEC Your_stored_procedure
Then you can get the result like this way
SELECT TOP 10 UserId, UserName
FROM #TempTable
ORDER BY UserId -- As #Squirrel's comment, TOP should come with ORDER BY
Note
You should make sure that the number of columns in your table according to the structure of the stored procedure.
Updated
As #Vinod Kumar's comment, you can also achieve it by using OPENQUERY like below
SELECT top 1 * FROM OPENQUERY ([MyServer], 'EXEC [VinodTest].[dbo].[tblAuthorsLarge] year = 2014')
You can use Fetch next clause. Please refer this for more information.
SELECT column-names
FROM table-name
ORDER BY column-names
OFFSET n ROWS
FETCH NEXT m ROWS ONLY

How to select more than 1 uniqueidentifier?

I would like to know if i can select more then 1 uniqueidentifier in SQL server.
To select 1 : SELECT NEWID() this brings back 1 result.
I would like to bring back like 50 results
EDIT:
I would like the results to be returned in 1 grid, so i can copy all of them at once. Not copy and paste 1 by 1.
Are you trying to do this in SQL Server Management Studio?
Try:
SELECT NEWID()
GO 50
and run this batch
Update:
OK - how about this then??
SELECT NEWID()
FROM master..spt_values
WHERE name IS NULL
AND number < 50
Assuming the master.dbo.sysobjects table has at least 50 system objects in it:
SELECT TOP 50 NEWID() FROM master.dbo.sysobjects WHERE xtype = 'S'
You don't need an order by, since the NEWID is random every time.
--run these queries independently
CREATE TABLE #temp1 (ID UniqueIdentifier)
GO
INSERT INTO #temp1
SELECT NewID() AS ID
GO 50
SELECT *
FROM #temp1
GO
DROP TABLE #temp1
GO

Copy table rows using OUTPUT INTO in SQL Server 2005

I have a table which I need to copy records from back into itself. As part of that, I want to capture the new rows using an OUTPUT clause into a table variable so I can perform other opertions on the rows as well in the same process. I want each row to contain its new key and the key it was copied from. Here's a contrived example:
INSERT
MyTable (myText1, myText2) -- myId is an IDENTITY column
OUTPUT
Inserted.myId,
Inserted.myText1,
Inserted.myText2
INTO
-- How do I get previousId into this table variable AND the newly inserted ID?
#MyTable
SELECT
-- MyTable.myId AS previousId,
MyTable.myText1,
MyTable.myText2
FROM
MyTable
WHERE
...
SQL Server barks if the number of columns on the INSERT doesn't match the number of columns from the SELECT statement. Because of that, I can see how this might work if I added a column to MyTable, but that isn't an option. Previously, this was implemented with a cursor which is causing a performance bottleneck -- I'm purposely trying to avoid that.
How do I copy these records while preserving the copied row's key in a way that will achieve the highest possible performance?
I'm a little unclear as to the context - is this in an AFTER INSERT trigger.
Anyway, I can't see any way to do this in a single call. The OUTPUT clause will only allow you to return rows that you have inserted. What I would recommend is as follows:
DECLARE #MyTable (
myID INT,
previousID INT,
myText1 VARCHAR(20),
myText2 VARCHAR(20)
)
INSERT #MyTable (previousID, myText1, myText2)
SELECT myID, myText1, myText2 FROM inserted
INSERT MyTable (myText1, myText2)
SELECT myText1, myText2 FROM inserted
-- ##IDENTITY now points to the last identity value inserted, so...
UPDATE m SET myID = i.newID
FROM #myTable m, (SELECT ##IDENTITY - ROW_NUMBER() OVER(ORDER BY myID DESC) + 1 AS newID, myID FROM inserted) i
WHERE m.previousID = i.myID
...
Of course, you wouldn't put this into an AFTER INSERT trigger, because it will give you a recursive call, but you could do it in an INSTEAD OF INSERT trigger. I may be wrong on the recursive issue; I've always avoid the recursive call, so I've never actually found out. Using ##IDENTITY and ROW_NUMBER(), however, is a trick I've used several times in the past to do something similar.

SQL Server list of insert identities

I have a table with an autoincrement id that I am doing a
INSERT INTO ( ... ) SELECT ... FROM ...
Is there a way for me to get the list of id's that have been inserted?
I was thinking I could get the max id before the insert then after and assuming everything in between is new, but then if a row gets inserted from somewhere else I could run into problems. Is there a proper way to do this?
I am using SQL Server 2005
Use the output clause.
DECLARE #InsertedIDs table(ID int);
INSERT INTO YourTable
OUTPUT INSERTED.ID
INTO #InsertedIDs
SELECT ...
Create a table variable and then use the OUTPUT clause into the table variable.
OUTPUT inserted.NameOfYourColumnId INTO tableVariable
Then you can SELECT from your table variable.

How can I do server side pagination of results in SQL Server 2000?

In SQL Server 2005, there is a feature called row_number() which makes pagination very simple.
SELECT * FROM table WHERE row_number() between x and y
Is there any SQL server way to do the same thing in SQL Server 2000?
(Note: I don't have access to a unique sequential numbering for the query, i.e. something which would be a synonym for row_number())
SELECT *
FROM (
SELECT TOP (Y - X ) *
FROM (
SELECT TOP Y *
FROM mytable
ORDER BY
column
) q
ORDER BY
column DESC
)
ORDER BY
column
Not sure if this is the most elegant solution, but it worked for me when we used SQL 2000...
If you're writing a stored procedure, you can do it with a temporary table.
Create a temporary table which has an automatically incrementing Identity column as well as the same columns as your result set.
Then, select the data from the result set and insert it into this temporary table (in the right order).
Finally, return results from your temporary table where the value of your Identity column acts as your row number.
You can also use cursor for this.
DECLARE #i INT
DECLARE C CURSOR FOR
SELECT ... FROM ... ORDER BY ...
OPEN C
FETCH ABSOLUTE #StartRow FROM C
SET #i = 1
WHILE (##FETCH_STATUS == 0) AND (#i < #EndRow - #StartRow) BEGIN
-- Do whatever you need
FETCH NEXT FROM C
END
CLOSE C
DEALLOCATE C
The only problem here is that each row is returned as a separate result set, but it does the job.

Resources