SpyProcedure does not support User-defined table type - tsqlt

Solved it (hopefully!)
I have a user-defined table data type used as a parameter in a stored procedure.
I did a spy on it and it throws an error like the this:
A column cannot be of a user-defined table type.[16,1]{,1}
Is it not supported? If not, I am interested on how anyone did it - I mean spy a stored procedure similar to my case.
My db server is SQL2008 R2.
Below is the sample code to replicate it:
CREATE TYPE [dbo].[UserDefinedTableType] AS TABLE
(
[col1] INT NULL
,[col2] NVARCHAR(MAX) NULL
)
GO
CREATE PROCEDURE dbo.Bar
#ItemsToProcess UserDefinedTableType READONLY
AS
GO
CREATE PROCEDURE dbo.Foo
#ItemsToProcess UserDefinedTableType READONLY
AS
EXEC dbo.Bar #ItemsToProcess = #ItemsToProcess
GO
CREATE PROCEDURE [testDatabase].[test spy stored procedure using user-defined table type]
AS
DECLARE #items AS UserDefinedTableType
EXEC tSQLt.SpyProcedure 'dbo.Bar';
EXEC [dbo].[Foo] #ItemsToProcess = #items;
GO
EXEC tSQLt.Run '[testDatabase].[test spy stored procedure using user-defined table type]'
Hacked code below.
I've marked my changes. The goal was to query values from a table-valued parameter as XML. Note: The code is not yet thoroughly tested.
---Build+
CREATE PROCEDURE tSQLt.Private_CreateProcedureSpy
#ProcedureObjectId INT,
#OriginalProcedureName NVARCHAR(MAX),
#LogTableName NVARCHAR(MAX),
#CommandToExecute NVARCHAR(MAX) = NULL
AS
BEGIN
DECLARE #Cmd NVARCHAR(MAX);
DECLARE #ProcParmList NVARCHAR(MAX),
#TableColList NVARCHAR(MAX),
#ProcParmTypeList NVARCHAR(MAX),
#TableColTypeList NVARCHAR(MAX);
DECLARE #Seperator CHAR(1),
#ProcParmTypeListSeparater CHAR(1),
#ParamName sysname,
#TypeName sysname,
#IsOutput BIT,
/*>>>*/ #IsCursorRef BIT,
/*>>>*/ #IsTableType BIT;
SELECT #Seperator = '', #ProcParmTypeListSeparater = '',
#ProcParmList = '', #TableColList = '', #ProcParmTypeList = '', #TableColTypeList = '';
DECLARE Parameters CURSOR FOR
SELECT p.name, t.TypeName, is_output, is_cursor_ref, tp.is_table_type
FROM sys.parameters p CROSS APPLY tSQLt.Private_GetFullTypeName(p.user_type_id,p.max_length,p.precision,p.scale,NULL) t
/*>>>*/ INNER JOIN sys.types tp
/*>>>*/ ON p.user_type_id = tp.user_type_id
WHERE object_id = #ProcedureObjectId;
OPEN Parameters;
/*>>>*/ FETCH NEXT FROM Parameters INTO #ParamName, #TypeName, #IsOutput, #IsCursorRef, #IsTableType;
WHILE (##FETCH_STATUS = 0)
BEGIN
IF #IsCursorRef = 0
BEGIN
SELECT #ProcParmList = #ProcParmList + #Seperator +
CASE WHEN #IsTableType = 1
/*>>>*/ THEN '(SELECT * FROM ' + #ParamName + ' for xml path(''''))'
ELSE
#ParamName
END
,
#TableColList = #TableColList + #Seperator + '[' + STUFF(#ParamName,1,1,'') + ']',
#ProcParmTypeList = #ProcParmTypeList
+ #ProcParmTypeListSeparater
+ #ParamName
+ ' '
+ #TypeName
/*>>>*/ + CASE WHEN #IsTableType = 1 THEN ' READONLY ' ELSE ' = NULL ' END
+ CASE WHEN #IsOutput = 1 THEN ' OUT' ELSE '' END,
#TableColTypeList = #TableColTypeList + ',[' + STUFF(#ParamName,1,1,'') + '] ' +
/*>>>*/ CASE WHEN #IsTableType = 1 -- If parameter is a user-defined table type.
/*>>>*/ THEN 'xml'
WHEN #TypeName LIKE '%nchar%'
OR #TypeName LIKE '%nvarchar%'
THEN 'nvarchar(MAX)'
WHEN #TypeName LIKE '%char%'
THEN 'varchar(MAX)'
ELSE #TypeName
END + ' NULL';
SELECT #Seperator = ',';
SELECT #ProcParmTypeListSeparater = ',';
END
ELSE
BEGIN
SELECT #ProcParmTypeList = #ProcParmTypeListSeparater + #ParamName + ' CURSOR VARYING OUTPUT';
SELECT #ProcParmTypeListSeparater = ',';
END;
/*>>>*/ FETCH NEXT FROM Parameters INTO #ParamName, #TypeName, #IsOutput, #IsCursorRef, #IsTableType;
END;
CLOSE Parameters;
DEALLOCATE Parameters;
DECLARE #InsertStmt NVARCHAR(MAX);
SELECT #InsertStmt = 'INSERT INTO ' + #LogTableName +
CASE WHEN #TableColList = '' THEN ' DEFAULT VALUES'
ELSE ' (' + #TableColList + ') SELECT ' + #ProcParmList
END + ';';
SELECT #Cmd = 'CREATE TABLE ' + #LogTableName + ' (_id_ int IDENTITY(1,1) PRIMARY KEY CLUSTERED ' + #TableColTypeList + ');';
EXEC(#Cmd);
SELECT #Cmd = 'CREATE PROCEDURE ' + #OriginalProcedureName + ' ' + #ProcParmTypeList +
' AS BEGIN ' +
#InsertStmt +
ISNULL(#CommandToExecute, '') + ';' +
' END;';
EXEC(#Cmd);
RETURN 0;
END;
---Build-

Related

FakeFunction Results based on Test

I'm using tSqlt to unit test a stored procedure. This stored proc joins to a table-valued function, the function takes no parameters and the results are filtered via the join on clause.
I'm writing multiple tests for the stored proc. Is there a way to to fake the function in such a way that I could return different results based on the test that is being run.
The only solution I can think of is to create a fake per test, which is possible but a little more than clunky.
I imagine an ideal solution would be some sort of variable exposed in tsqlt that would allow me to determine which test I'm in and use some sort of case statement or something.
I use following procedure for that. It is not ideal, but working:
CREATE PROCEDURE [tSQLt].[FakeFunction2]
#FunctionName VARCHAR(200)
, #SchemaName VARCHAR(200) = 'dbo'
, #tmpTableName VARCHAR(200)
AS
BEGIN
DECLARE #Params VARCHAR(2000);
DECLARE #NewName VARCHAR(MAX) = #FunctionName + REPLACE(CAST(NEWID() AS VARCHAR(100)), '-', '');
DECLARE #FunctionNameWithSchema VARCHAR(MAX) = #SchemaName + '.' + #FunctionName;
DECLARE #RenameCmd VARCHAR(MAX) = 'EXEC sp_rename ''' + #FunctionNameWithSchema + ''', ''' + #NewName + ''';';
DECLARE #newTbleName VARCHAR(200) = #SchemaName + '.tmp' + REPLACE(CAST(NEWID() AS VARCHAR(100)), '-', '');
DECLARE #newTblStmt VARCHAR(2000) = 'SELECT * INTO ' + #newTbleName + ' FROM ' + #tmpTableName;
EXEC tSQLt.SuppressOutput #command = #newTblStmt;
SELECT #Params = p.params
FROM
( SELECT DISTINCT ( SELECT p1.name + ' ' + type1.name + b.brk + ',' AS [text()]
FROM sys.types type1
JOIN sys.parameters p1 ON p1.system_type_id = type1.system_type_id
CROSS APPLY
( SELECT CASE WHEN type1.name LIKE '%char' OR type1.name = 'varbinary' THEN
REPLACE(
'(' + CAST(p1.max_length AS VARCHAR(5)) + ')', '-1', 'MAX')
WHEN type1.name IN ('decimal', 'numeric') THEN
'(' + CAST(p1.precision AS VARCHAR(5)) + ', '
+ CAST(p1.scale AS VARCHAR(5)) + ')'
WHEN type1.name IN ('datetime2') THEN
'(' + CAST(p1.scale AS VARCHAR(5)) + ')'
ELSE ''
END AS brk) b
WHERE p1.object_id = p.object_id
ORDER BY p1.parameter_id
FOR XML PATH('')) [parameters]
FROM sys.objects AS o
LEFT JOIN sys.parameters AS p ON p.object_id = o.object_id
LEFT JOIN sys.types AS t ON t.system_type_id = p.system_type_id
WHERE o.name = #FunctionName AND o.schema_id = SCHEMA_ID(#SchemaName)) [Main]
CROSS APPLY
(SELECT LEFT(Main.[parameters], LEN(Main.[parameters]) - 1) params) AS p;
EXEC tSQLt.SuppressOutput #command = #RenameCmd;
DECLARE #newFunctionStmt VARCHAR(MAX) = '';
SET #newFunctionStmt = 'CREATE FUNCTION [' + #SchemaName + '].[' + #FunctionName + '](' + COALESCE(#Params,'') + ')';
SET #newFunctionStmt = #newFunctionStmt + ' RETURNS TABLE AS RETURN (SELECT * FROM ' + #newTbleName + ');';
EXEC tSQLt.SuppressOutput #command = #newFunctionStmt;
END;
and usage:
INSERT INTO #table
(col1
, col2
, col3)
VALUES
('a', 'b', 'c'),
('d', 'e', 'f');
EXEC tSQLt.FakeFunction2 #FunctionName = 'function_name'
, #SchemaName = 'dbo'
, #tmpTableName = '#table';
now with any passed parameter to that function it will always return the values from #table temp table
I thought of one potential solution.
I create a table within the test class schema and populate it with the results I wish to be returned per test.
CREATE TABLE testcalass.fakefunction_Results
(
ID INT,
Value NUMERIC(12, 5)
)
GO
CREATE FUNCTION testcalass.fakefunction()
RETURNS #results TABLE
(
ID INT,
Value NUMERIC(12, 5)
)
BEGIN
INSERT INTO #results
SELECT ID, Value FROM testcalass.fakefunction_Results
END
GO
So basically, I can populate is functions results at the top of my tests during the assemble section.

Querying million records with paging and custom searching using SQL stored procedure

I need help on optimizing this query that retrieves a list of products from businesses. This query only brings set of data using specific parameters you see below. It takes about 6-9 seconds to run with about 40,000 products and only brings 10 products at a time, but I need to make it faster.
I execute this:
EXEC [GetProducts] #StartRowIndex=0, #MaximumRows=10,
#SortedBy='ProductName', #SortedIn='DESC', #CategoryID=0,
#CategoryIDPath=N'''1|%''', #SearchText='ALL', #SearchSQL=N'', #CreatedByUser=0
Here's the full query:
ALTER PROCEDURE [GetProducts] (
#StartRowIndex int,
#MaximumRows int,
#SortedBy nvarchar(20),
#SortedIn nvarchar(6),
#CategoryID int,
#CategoryIDPath nvarchar(500),
#SearchText nvarchar(255),
#SearchSQL nvarchar(MAX),
#CreatedByUser int
)
as
BEGIN
--get correct Sorted By
DECLARE #strSortedBy nvarchar(300)
SET #strSortedBy =
(CASE
WHEN (#SortedBy = 'CreatedDate') THEN 'Products.CreatedDate ' + #SortedIn
WHEN (#SortedBy = 'Views') THEN 'Products.Views ' + #SortedIn
ELSE 'Products.ProductName ' + #SortedIn
END)
--check if you are filtering by Category START
DECLARE #FilterByCategoryID nvarchar(250)
IF (#CategoryID > 0)
BEGIN
SET #FilterByCategoryID = 'AND Products.CategoryID = ' + cast(#CategoryID as nvarchar(5))
END
else
BEGIN
IF (#CategoryIDPath <> '') --show category features first then the most recent by default
BEGIN
SET #FilterByCategoryID = 'AND Products.CategoryIDPath LIKE ' + #CategoryIDPath
END
else
BEGIN
SET #FilterByCategoryID = ''
END
END
--check if you are filtering by Category END
--this option is used when you are searching by category only START
IF (#SearchText <> '')
BEGIN
IF #SearchSQL = 'ALL'
BEGIN
SET #SearchSQL = ''
END
END
else
BEGIN
SET #SearchSQL = ''
END
--this option is used when you are searching by category only END
--check if you are filtering by CreatedByUser START
DECLARE #FilterByCreatedByUser nvarchar(250)
IF (#CreatedByUser > 0)
BEGIN
SET #FilterByCreatedByUser = 'AND Products.CreatedByUser = ' + cast(#CreatedByUser as nvarchar(10))
END
else
BEGIN
SET #FilterByCreatedByUser = ''
END
--check if you are filtering by CreatedByUser END
DECLARE #MaximumRow int
SET #MaximumRow = #startRowIndex + #maximumRows
exec('SELECT
RowRank
,Products.ItemID
,Products.ProductName
,Products.Description
,Products.CategoryID
,Products.CategoryIDPath
,Products.FileName
,Products.CategoryName
,Businesses.BusinessName
,Businesses.Country
,Products.TotalCount
FROM
(
SELECT
ROW_NUMBER() OVER(ORDER BY ' + #strSortedBy + ') AS RowRank
,COUNT(*) OVER() AS TotalCount
,Products.*
FROM
Products
INNER JOIN Businesses
ON Products.CreatedByUser = Businesses.CreatedByUser
AND Businesses.Published <> 0
AND (Businesses.[ExpireDate] >= GetDate() or Businesses.[ExpireDate] is null)
WHERE
Products.Published <> 0
AND (Products.[ExpireDate] >= GetDate() OR Products.[ExpireDate] is null)
AND Products.ItemType = ''Classifieds''
' + #FilterByCategoryID + '
' + #FilterByCreatedByUser + '
' + #SearchSQL + '
) AS Products
INNER JOIN Businesses
ON Products.CreatedByUser = Businesses.CreatedByUser
AND Businesses.Published <> 0
AND (Businesses.[ExpireDate] >= GetDate() or Businesses.[ExpireDate] is null)
WHERE
RowRank > ' + #startRowIndex + ' AND RowRank <= ' + #MaximumRow + '
ORDER BY ' + #strSortedBy)
END

Catch the sp_executesql table Result

I Have Stored Procedure by using sp_executesql:
USE [databasedevelopment]
GO
/****** Object: StoredProcedure [dbo].[SearchPaymentDev] Script Date: 06/03/2013 16:42:49 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER Procedure [dbo].[SearchPaymentDev]
#PayAccountin as varchar(10),
#PayCustNamein as varchar(30),
#PayAmountin as int,
#PayAmountPaidin as int,
#PayResponsein as char (2),
#PayRefNoin as varchar (120),
#PayScreenTextin as varchar (100),
#PayReceiptTextin as varchar (350),
#PayDatetimein as varchar(50),
#PayBankCodein as varchar (6)
AS
Set NoCount ON
Declare #SQLQuery AS NVarchar(4000)
Declare #ParamDefinition AS NVarchar(2000)
Set #SQLQuery = 'Select * From payment where PayId is not null '
If #PayAccountin Is Not Null
Set #SQLQuery = #SQLQuery + ' And (PayAccount LIKE ''%'' + #PayAccountin + ''%'')'
If #PayCustNamein Is Not Null
Set #SQLQuery = #SQLQuery + ' And (PayCustName LIKE ''%'' + #PayCustNamein + ''%'')'
If #PayAmountin Is Not Null
Set #SQLQuery = #SQLQuery + ' And (PayAmount LIKE ''%'' + #PayAmountin + ''%'')'
If #PayAmountPaidin Is Not Null
Set #SQLQuery = #SQLQuery + ' And (PayAmountPaid LIKE ''%'' + #PayAmountPaidin + ''%'')'
If #PayResponsein is Not Null
Set #SQLQuery = #SQLQuery + ' And (PayResponse LIKE ''%'' + #PayResponsein + ''%'')'
If #PayRefNoin is Not Null
Set #SQLQuery = #SQLQuery + ' And (PayRefNo LIKE ''%'' + #PayRefNoin + ''%'')'
If #PayBankCodein is Not Null
Set #SQLQuery = #SQLQuery + ' And (PayBankCode LIKE ''%'' + #PayAccountin + ''%'')'
If #PayDatetimein is Not Null
Set #SQLQuery = #SQLQuery + ' And (cast(PayDatetime as date) = ( select convert(date , #PayDatetimein , 103)))'
Set #ParamDefinition =
'#PayAccountin as varchar(10),
#PayCustNamein as varchar(30),
#PayAmountin as int,
#PayAmountPaidin as int,
#PayResponsein as char (2),
#PayRefNoin as varchar (120),
#PayBankCodein as varchar (6),
#PayDatetimein as varchar(50)'
Execute sp_Executesql
#SQLQuery,
#ParamDefinition,
#PayAccountin,
#PayCustNamein,
#PayAmountin,
#PayAmountPaidin,
#PayResponsein,
#PayRefNoin,
#PayBankCodein,
#PayDatetimein
If ##ERROR <> 0 GoTo ErrorHandler
Set NoCount OFF
Return(0)
ErrorHandler:
Return(##ERROR)
Right now i use the stored procedure on vb.net code behind and get the data as datatable and process on VB.net Code behind.
but now I Want to get the table result query and progress to the same stored procedure to change some of the field value, is it possible to catch the table first on the stored procedure, change the value and give output to be used on vb.net ?
thanks for your help.
Try this one -
ALTER PROCEDURE [dbo].[SearchPayment]
#PayAccountin AS VARCHAR(10),
#PayCustNamein AS VARCHAR(30),
#PayAmountin AS INT,
#PayAmountPaidin AS INT,
#PayResponsein AS CHAR (2),
#PayRefNoin AS VARCHAR (120),
#PayScreenTextin AS VARCHAR (100),
#PayReceiptTextin AS VARCHAR (350),
#PayDatetimein AS VARCHAR(50),
#PayBankCodein AS VARCHAR (6)
AS BEGIN
SET NOCOUNT ON
SET XACT_ABORT ON
DECLARE #OwnTran BIT
SET #OwnTran = 0
IF ##TRANCOUNT = 0
BEGIN
SET #OwnTran = 1
BEGIN TRAN
END
BEGIN TRY
DECLARE #SQLQuery NVARCHAR(4000)
SELECT #SQLQuery = '
IF OBJECT_ID (N''tempdb.dbo.##test'') IS NOT NULL
DROP TABLE ##test
SELECT *
INTO ##test
FROM payment
WHERE PayId is not null '
+ ISNULL(' And (PayAccount LIKE ''%''' + #PayAccountin + '''%'')', '')
+ ISNULL(' And (PayCustName LIKE ''%''' + #PayCustNamein + '''%'')', '')
+ ISNULL(' And (PayAmount LIKE =' + CAST(#PayAmountin AS VARCHAR(5)) + ')', '')
+ ISNULL(' And (PayAmountPaid =' + CAST(#PayAmountPaidin AS VARCHAR(5)) + ')', '')
+ ISNULL(' And (PayResponse LIKE ''%''' + #PayResponsein + '''%'')', '')
+ ISNULL(' And (PayRefNo LIKE ''%''' + #PayRefNoin + '''%'')', '')
+ ISNULL(' And (PayBankCode LIKE ''%''' + #PayAccountin + '''%'')', '')
+ ISNULL(' And (cast(PayDatetime as date) = convert(date, #PayDatetimein , 103))', '')
EXEC sys.sp_Executesql #SQLQuery
END TRY
BEGIN CATCH
IF ##TRANCOUNT > 0
ROLLBACK TRAN
END CATCH
IF #OwnTran = 1
AND ##TRANCOUNT > 0
BEGIN
COMMIT TRAN
END
END

sql create table with stored procedure with optional parameters

I am writing a report based on parameters, utilizing a sql stored procedure. Problem is there are several 'optional' parameters, where the user can choose a value, or ignore that parameter altogether. I need to use the stored proc as a dataset in asp.net report. Only way I thought of doing it is to create a table from the results. But I'm clueless.
How do I turn this into a 'create table' stored proc?
Any assistance is greatly appreciated.
Cindy
This is what I have so far -
ALTER PROCEDURE [dbo].[rspSCL]
-- Add the parameters for the stored procedure here
(#year as int,
#RRID as int,
#State as nchar(2),
#Sub as varchar(75),
#app as int,
#sprayed as int,
#subcontracted as int,
#thirdapp as bit)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
DECLARE #SQL as varchar(4000)
DECLARE #SUBQ AS varchar(400)
--what fields need to be seen
SET #SQL = 'SELECT C.CRID, C.DOT, C.RR, C.Pref, C.MP, C.Division, C.Subdivision,C.City, C.Street,
C.State, C.County, C.RestrictedCounty, C.Remarks, C.SpecialInstructions, C.Route, C.ThirdAppRequired,
C.MainTrks, C.OtherTrks, C.OnSpur, C.MaxSpeed, C.SubContracted, C.FenceEncroachment, C.Lat, C.Long,
C.PropertyType, C.WarningDevice,C.Surface, C.ROWNE, C.ROWNW, C.ROWSE, C.ROWSW, C.ROWWidth, C.ExtNE,
C.ExtNW, C.ExtSE, C.ExtSW, C.TempActive, A.Spray, A.ContractYear'
SET #SUBQ =
CASE WHEN #app = 1 THEN
'FROM Crossings LEFT OUTER JOIN
(select A.CRID, A.spray FROM ApplicationData A
WHERE A.ContractYear = ' + CAST( #year AS varchar(4)) + ') as APPS
ON Crossings.CRID = APPS.CRID'
WHEN #app = 2 THEN
'FROM Crossings inner join
(SELECT crid, C,OUNT(APPID)as count
from ApplicationData
where ContractYear = ' + CAST( #year AS varchar(4)) + '
group by CRID) as APPS
ON Crossings.CRID = APPS.CRID
WHERE Crossings.RR = '+ CAST( #RRID AS varchar(4)) + '
and crossings.state = '+ #state + '
and count = 1'
when #app = 3 THEN
'FROM Crossings inner join
(SELECT crid, COUNT(APPID)as count
from ApplicationData
where ContractYear = ' + CAST( #year AS varchar(4)) + '
group by CRID) as APPS
ON Crossings.CRID = APPS.CRID
WHERE Crossings.RR = '+ CAST( #RRID AS varchar(4)) + '
and crossings.state = '+ #state + '
and count = 2'
ELSE ''
END
--add the FROM to the query
SET #SQL = #SQL + #SUBQ
--add the subdivision to the where statement
If #Sub != 'ALL'
SET #SQL = #SQL + 'AND (C.Subdivision = ' + #Sub + ')'
ELSE
SET #SQL = #SQL
--add sprayed to where
DECLARE #S as varchar(100)
SET #S =
CASE WHEN #sprayed = 1 THEN
'AND (A.sprayed = 1)'
WHEN #sprayed = 0 THEN
'AND (A.sprayed = 0)'
ELSE
''
END
SET #SQL = #SQL + #S
--add subcontracted to where
DECLARE #C as varchar (100)
SET #C =
CASE WHEN #subcontracted = 0 THEN
'AND (C.subcontracted = 0)'
WHEN #subcontracted = 1 THEN
'AND (C.subcontracted = 1)'
ELSE
''
END
SET #SQL = #SQL + #C
IF #thirdapp = 1
SET #SQL = #SQL + 'AND (C.ThirdAppRequired = 1)'
ELSE
SET #SQL = #SQL
END

Paging in my web page

I have a large data set and i have to apply paging on that data set and after that the result set should be another data set. What is the reliable method to achieve that.
I have tried with 'PagedDataSource' class but i don't know how it is possible to convert to dataset or data table.
In my case i need a general solution. I have to bind to a control like gridview as well as i have to used it with normal html table.
check this article doing same thing you want : http://www.codeproject.com/KB/custom-controls/EnhanceGrid.aspx
following sp returns record that you want
CREATE PROCEDURE [dbo].[GetRequestedRecordByPage]
#FromList nvarchar(200) -- Table Name
,#SortingCol nvarchar(200) -- Sorting column Name
,#SelectList nvarchar(200) = '*' -- Select columns list
,#WhereClause nvarchar(200) = '' -- Where clause i.e condition
,#PageNum int = 1 -- Requested page number
,#PageSize int = 5 -- No of record in page
,#TotalNoOfRecord int output -- Total no of selected records
AS
Begin
SET NOCOUNT ON
DECLARE #Query nvarchar(max) -- query going to be execute
IF rtrim(ltrim(#WhereClause)) <> ''
BEGIN
SET #Query ='SELECT #TotalNoOfRecord = COUNT(*)
FROM ' + #FromList + '
WHERE ' + #WhereClause
END
ELSE
BEGIN
SET #Query ='SELECT #TotalNoOfRecord = COUNT(*)
FROM ' + #FromList
END
/* Count no. of record */
EXEC sp_executeSQL
#Query,
#params = N'#TotalNoOfRecord INT OUTPUT',
= #TotalNoOfRecord OUTPUT
DECLARE #lbound int, #ubound int
/* Calculating upper and lower bound */
SET #lbound = ((#PageNum - 1) * #PageSize)
SET #ubound = #lbound + #PageSize + 1
/* Get list of record(s) */
SELECT #Query = ''
SELECT #Query = 'SELECT *
FROM (
SELECT ROW_NUMBER() OVER(ORDER BY ' + #SortingCol + ') AS rownumber,' +#SelectList +
' FROM ' + #FromList
IF rtrim(ltrim(#WhereClause)) <> ''
BEGIN
SELECT #Query = #Query + ' WHERE ' + #WhereClause
END
SELECT #Query = #Query + ' ) AS tbl
WHERE rownumber > ' + CONVERT(varchar(9), #lbound) +
' AND rownumber < ' + CONVERT(varchar(9), #ubound)
EXEC (#Query)
End

Resources