I want to execute below stored procedure against multiple tables, by passing table name as parameter.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
CREATE PROCEDURE GETARTICLESPAGEWISE
#PageIndex INT = 1
,#PageSize INT = 10
,#ArticleCategory varchar(100) = 'null'
,#RecordCount INT OUTPUT
AS
BEGIN
SET NOCOUNT ON;
SELECT ROW_NUMBER() OVER
(
ORDER BY [ArticleID] ASC
)AS RowNumber
,[ArticleID]
,[ArticleName]
,[ArticleCategory]
INTO #ResultSet
FROM [ASPDOTNETARTICLES]
WHERE ArticleCategory = #ArticleCategory
SELECT #RecordCount = COUNT(*)
FROM #ResultSet
SELECT * FROM #ResultSet
WHERE RowNumber BETWEEN(#PageIndex -1) * #PageSize + 1 AND(((#PageIndex -1) * #PageSize + 1) + #PageSize) - 1
DROP TABLE #ResultSet
END
GO
--EXEC dbo.GETARTICLESPAGEWISE #PageIndex =1, #PageSize = 2, #ArticleCategory='Gridview',#RecordCount=0
I tried but error occurred, tried stored procedure
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
ALTER PROCEDURE GETARTICLESPAGEWISEGENERIC
#PageIndex INT = 1
,#PageSize INT = 10
,#ArticleCategory varchar(100) = 'null'
,#RecordCount INT OUTPUT
,#TableName varchar(100) = 'NULL'
AS
BEGIN
DECLARE #columnList varchar(200)
SET #columnList=' SELECT ROW_NUMBER() OVER
(
ORDER BY [ArticleID] ASC
)AS RowNumber
,[ArticleID]
,[ArticleName]
,[ArticleCategory]'
SET NOCOUNT ON;
DECLARE #sqlCommand varchar(300)
set #sqlCommand ='
SELECT '+ #columnList +'
INTO #ResultSet
FROM '+ #TableName +'
WHERE ArticleCategory ='+ #ArticleCategory+'
//i got the error in this statement
SELECT #RecordCount = COUNT(*)
FROM #ResultSet
SELECT * FROM #ResultSet
// i got the error in this statement
WHERE RowNumber BETWEEN(#PageIndex -1) * #PageSize + 1 AND(((#PageIndex -1) * #PageSize + 1) + #PageSize) - 1
DROP TABLE #ResultSet'
END
GO
Can u give solution for this problem?
Try this one -
CREATE PROCEDURE GETARTICLESPAGEWISE
#PageIndex INT = 1
, #PageSize INT = 10
, #ArticleCategory VARCHAR(100) = 'null'
, #TableName VARCHAR(100) = 'dbo.ASPDOTNETARTICLES'
, #RecordCount INT OUTPUT
AS BEGIN
SET NOCOUNT ON;
IF OBJECT_ID (N'tempdb.dbo.##ResultSet') IS NOT NULL
DROP TABLE ##ResultSet
DECLARE #SQL NVARCHAR(MAX) = '
SELECT
RowNumber = ROW_NUMBER() OVER (ORDER BY ArticleID)
, ArticleID
, ArticleName
, ArticleCategory
INTO ##ResultSet
FROM ' + #TableName + '
WHERE ArticleCategory = ''' + #ArticleCategory + ''''
EXEC sys.sp_executesql #SQL
SELECT #RecordCount = COUNT(*)
FROM ##ResultSet
SELECT *
FROM ##ResultSet
WHERE RowNumber BETWEEN (#PageIndex - 1) * #PageSize + 1 AND (((#PageIndex - 1) * #PageSize + 1) + #PageSize) - 1
END
create a table which will hold all the table names to be processed and loop through this table inside your sproc.
Related
ALTER PROCEDURE [dbo].[GetCustomers_PagerSelected]
#PageIndex INT,
#PageSize INT = 10,
#SubCondition nvarchar(max),
#RecordCount INT OUTPUT
AS
BEGIN
SET NOCOUNT ON;
SELECT
ROW_NUMBER() OVER (ORDER BY [Plan_Id] ASC) AS RowNumber,
[Plan_Id], [User_Id], [Plan_Name],
[ImageCount], [PlanPrice],
'../User/HomePlanImage/' + CONVERT(varchar(5), User_Id ) +'/' + CONVERT(varchar(5), Plan_Id ) + '/' + CONVERT(varchar(5),1) +'.jpg' AS PlanImagePath
INTO
#Results
FROM
[mf_BuildingPlanDetails]
WHERE
IsActive = 1 #SubCondition
SELECT
#RecordCount = COUNT(*)
FROM
#Results
SELECT *
FROM #Results
WHERE
RowNumber BETWEEN(#PageIndex -1) * #PageSize + 1 AND(((#PageIndex -1) * #PageSize + 1) + #PageSize) - 1
DROP TABLE #Results
Something like this should probably do what you want:
ALTER PROCEDURE [dbo].[GetCustomers_PagerSelected]
#PageIndex INT,
#PageSize INT = 10,
#SubCondition nvarchar(max),
#RecordCount INT OUTPUT
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Sql varchar(max)
CREATE TABLE #Results
(
RowNumber int,
Plan_Id int, -- Guessing the column data type, change if needed
User_Id int, -- Guessing the column data type, change if needed
Plan_Name varchar(200), -- Guessing the column data type and lengthe, change if needed
ImageCount int, -- Guessing the column data type, change if needed
PlanPrice money, -- Guessing the column data type, change if needed
PlanImagePath varchar(300), -- Guessing the column data type and lengthe, change if needed
)
SET #Sql = '
SELECT
ROW_NUMBER() OVER (ORDER BY [Plan_Id] ASC) AS RowNumber,
[Plan_Id],
[User_Id],
[Plan_Name],
[ImageCount],
[PlanPrice],
''../User/HomePlanImage/'' + CONVERT(varchar(5), User_Id ) +
''/'' + CONVERT(varchar(5), Plan_Id ) +
''/'' + CONVERT(varchar(5),1) +
''.jpg'' AS PlanImagePath
FROM
[mf_BuildingPlanDetails]
WHERE
IsActive = 1 ' + #SubCondition
INSERT INTO #Results
EXEC sp_executeSql #Sql
SELECT
#RecordCount = COUNT(*)
FROM
#Results
SELECT *
FROM #Results
WHERE
RowNumber BETWEEN(#PageIndex -1) * #PageSize + 1 AND(((#PageIndex -1) * #PageSize + 1) + #PageSize) - 1
DROP TABLE #Results
END
However, Please note that using a query like this is a security hazard since it's vulnerable to SQL injection attacks.
I would strongly recommend a different approach, however I can't advise on that because I don't have enough information.
Below store procedure gives following error
com.microsoft.sqlserver.jdbc.SQLServerException: Ambiguous column name 'Incident_id'
USE [FusionSysLive]
GO
/****** Object: StoredProcedure [dbo].[RCPT_Search_Reports] Script ****/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[RCPT_Search_Reports]
#pagesize int = 10,
#pagestart int= 0,
#querysrting varchar(20) = '',
#orderBy varchar(40)= '',
#incident_id numeric(9) =null,
#searchdate varchar(20) =null ,
#search_string varchar(40) =null ,
#action_type varchar(40) =null ,
#security_grp_id numeric(10),
#company_id numeric(10)
as
set nocount on
set quoted_identifier off
CREATE TABLE #Temp (
Row numeric(10, 0) ,
Incident_id numeric(10, 0) null,
Description varchar(50),
Creation_timestamp varchar(100) null,
)
set nocount on
set quoted_identifier off
declare #query varchar(max)
set #query = 'select ROW_NUMBER() OVER (order by '+#orderBy +') AS Row,inc.Incident_id, inc.Description, inc.Creation_timestamp from Incident inc, Incident_list incl where inc.Incident_id = incl.Incident_id '
If(#security_grp_id = 1)
Begin
Set #query = #query + 'and (inc.Company_id ='+cast(#company_id as varchar)+' or inc.Company_id is null) '
End
Else
Begin
Set #query = #query + 'and inc.Company_id ='+cast(#company_id as varchar)
End
If ( ( #incident_id<>0 and #incident_id is not null) or ( (#action_type = 'byGroupID' or #action_type = 'byGroupName' ) and #incident_id=0 and #search_string='' and #searchdate='' ))
Begin
Set #query = #query + ' and inc.Incident_id=' + cast(#incident_id as varchar)
End
If (#action_type is not null and #search_string is not null and #action_type!='' and #search_string!='' )
Begin
If (#action_type = 'byGroupID')
Begin
Set #query = #query + ' and incl.Recipient_list_id in (select Group_id from Contact_group where Group_id like '''+ #search_string + '%'') '
End
Else If (#action_type = 'byGroupName')
Begin
Set #query = #query + ' and incl.Recipient_list_id in (select Group_id from Contact_group where Group_name like '''+ #search_string + '%'') '
End
End
If (#searchdate is not null and #searchdate!='' )
Begin
Set #query = #query + ' and CONVERT(datetime, FLOOR(CONVERT(float(24), Creation_timestamp))) =''' + #searchdate + ''''
End
set #query = #query + ' order by inc.Incident_id';
print #query
insert into #Temp exec(#query)
select row ,Incident_id , Description , Creation_timestamp
from #Temp where Row > #pagestart and row <= (#pagestart + #pagesize)
select count(*) as total_count from #Temp
drop table #Temp
alter PROCEDURE sp_Get_CustInfoSerach2
(#PageIndex INT = 1
,#PageSize INT = 10
,#RecordCount INT OUTPUT
,#ColumnName VARCHAR(50)=null
,#Value VARCHAR(50)=null
,#ddlValue VARCHAR(50)=null
,#txtValue VARCHAR(50)=null
,#status varchar(30))
AS
BEGIN
SET NOCOUNT ON;
DECLARE #cmd AS NVARCHAR(max)
if #txtValue IS NULL
Begin
SET #Value = ''''+#ddlValue+ ''''
End
else if #ddlValue IS NULL
begin
SET #Value = ''''+#txtValue+ ''''
end
SET #cmd = 'SELECT ROW_NUMBER() OVER
(
ORDER BY C_Register.UserId desc
)AS RowNumber
,C_Register.UserId, C_Register.Name, C_Register.UserName, C_Register.Status,
Packages.PackagePeriod, Packages.PackageName, C_Register.ActivationDate,
Receive_Payment.OldExpiryDate, Receive_Payment.Balance, Receive_Payment.PyingAmount,
Receive_Payment.LastPaidDate, C_Register.LastUpdateTime,
Area.AreaName, C_Register.MobNo, Employee.EmpName, C_Register.Address,C_Register.CreatedDate
INTO'+ #Results+'
FROM C_Register INNER JOIN Receive_Payment ON C_Register.UserId = Receive_Payment.UserId
INNER JOIN Area ON C_Register.AreaId = Area.AreaId
INNER JOIN Employee ON Receive_Payment.EmpId = Employee.EmpId
INNER JOIN Packages ON Receive_Payment.PackageId = Packages.PackageId
where C_Register.AccountExpiry= Receive_Payment.OldExpiryDate And C_Register.Status = '+#status+'And
' + #ColumnName + ' = ' + #Value
SELECT #RecordCount = COUNT(*)
FROM #Results
SELECT * FROM #Results
WHERE RowNumber BETWEEN(#PageIndex -1) * #PageSize + 1 AND(((#PageIndex -1) * #PageSize + 1) + #PageSize) - 1
DROP TABLE #Results
EXEC(#cmd)
END
throwing error:
Invalid column name '#Results'.
how to solve it?
If i understand your problem correctly you should first exec dynamic sql before select from temporary table
Alter PROCEDURE sp_Get_CustInfoSerach2
(
#PageIndex INT = 1 ,
#PageSize INT = 10 ,
#RecordCount INT OUTPUT ,
#ColumnName VARCHAR(50)=null ,
#Value VARCHAR(50)=null ,
#ddlValue VARCHAR(50)=null ,
#txtValue VARCHAR(50)=null ,
#status varchar(30)
)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #cmd AS NVARCHAR(max)
If #txtValue IS NULL
Begin
SET #Value = ''''+#ddlValue+ ''''
End
Else
if #ddlValue IS NULL
Begin
SET #Value = ''''+#txtValue+ ''''
End
SET #cmd = 'SELECT ROW_NUMBER() OVER ( ORDER BY C_Register.UserId desc )AS RowNumber,
C_Register.UserId, C_Register.Name, C_Register.UserName, C_Register.Status,
Packages.PackagePeriod, Packages.PackageName, C_Register.ActivationDate,
Receive_Payment.OldExpiryDate, Receive_Payment.Balance, Receive_Payment.PyingAmount,
Receive_Payment.LastPaidDate, C_Register.LastUpdateTime,
Area.AreaName, C_Register.MobNo, Employee.EmpName, C_Register.Address,C_Register.CreatedDate
INTO #Results
FROM C_Register INNER JOIN Receive_Payment ON C_Register.UserId = Receive_Payment.UserId
INNER JOIN Area ON C_Register.AreaId = Area.AreaId
INNER JOIN Employee ON Receive_Payment.EmpId = Employee.EmpId
INNER JOIN Packages ON Receive_Payment.PackageId = Packages.PackageId
where C_Register.AccountExpiry= Receive_Payment.OldExpiryDate And C_Register.Status = '+#status+'And
' + #ColumnName + ' = ' + #Value
/*First Execute above dynamic Sql query */
EXEC(#cmd)
/* From the above execute statemnet the query will executed and temporary table will created on the fly */
SELECT #RecordCount = COUNT(*)
FROM #Results
SELECT * FROM #Results
WHERE RowNumber BETWEEN(#PageIndex -1) * #PageSize + 1 AND(((#PageIndex -1) * #PageSize + 1) + #PageSize) - 1
DROP TABLE #Results
Problem in your query is creation of temp table thats not right way to create temp table inside dynamic query.
But even if you create temp table inside a dynamic query it can be accessed only inside the session of dynamic query. If you try to select the temp outside of dynamic query which is created inside the dynamic query you will get a error saying object doesnot exist.
Since you know the number of columns present in the result of dynamic query you can create the temp table outside of dynamic query and insert the records through dynamic query.
Try changing your procedure like this.
ALTER PROCEDURE Sp_get_custinfoserach2 (#PageIndex INT = 1,
#PageSize INT = 10,
#RecordCount INT output,
#ColumnName VARCHAR(50)=NULL,
#Value VARCHAR(50)=NULL,
#ddlValue VARCHAR(50)=NULL,
#txtValue VARCHAR(50)=NULL,
#status VARCHAR(30))
AS
BEGIN
SET nocount ON;
DECLARE #cmd AS NVARCHAR(max)
IF #txtValue IS NULL
BEGIN
SET #Value = '''' + #ddlValue + ''''
END
ELSE IF #ddlValue IS NULL
BEGIN
SET #Value = '''' + #txtValue + ''''
END
/*create a temp as same structure of your dynamic query select statement*/
CREATE TABLE #result
(
rownum INT,
userid INT,
NAME VARCHAR(100),
username VARCHAR(100),
status VARCHAR(15),
packageperiod VARCHAR(15),
packagename VARCHAR(100),
activationdate DATETIME,
oldexpirydate DATETIME,
balance NUMERIC(22, 4),
pyingamount NUMERIC(22, 4),
lastpaiddate DATETIME,
lastupdatetime DATETIME,
areaname VARCHAR(100),
mobno INT,
empname VARCHAR(100),
address VARCHAR(5000),
createddate DATETIME
)
SET #cmd =
' Insert into #result
SELECT ROW_NUMBER() OVER (ORDER BY C_Register.UserId desc )AS RowNumber,
C_Register.UserId, C_Register.Name, C_Register.UserName,
C_Register.Status, Packages.PackagePeriod, Packages.PackageName,
C_Register.ActivationDate,Receive_Payment.OldExpiryDate,
Receive_Payment.Balance, Receive_Payment.PyingAmount,
Receive_Payment.LastPaidDate, C_Register.LastUpdateTime,
Area.AreaName, C_Register.MobNo, Employee.EmpName,
C_Register.Address,C_Register.CreatedDate
FROM C_Register
INNER JOIN Receive_Payment
ON C_Register.UserId = Receive_Payment.UserId
INNER JOIN Area
ON C_Register.AreaId = Area.AreaId
INNER JOIN Employee
ON Receive_Payment.EmpId = Employee.EmpId
INNER JOIN Packages
ON Receive_Payment.PackageId = Packages.PackageId
where C_Register.AccountExpiry= Receive_Payment.OldExpiryDate And C_Register.Status = ' + #status + ' And ' + #ColumnName + ' = ' + #Value
SELECT #RecordCount = Count(*)
FROM #results
SELECT *
FROM #results
WHERE rownumber BETWEEN( #PageIndex - 1 ) * #PageSize + 1 AND( (
( #PageIndex - 1 ) * #PageSize + 1 ) +
#PageSize ) - 1
DROP TABLE #results
EXEC(#cmd)
END
Note : I have given generic datatypes to temp table columns please change the datetypes according to your schema.
**
I have make a Stored procedure in sql-server 2008 for search
purpose,Below code represents my stored procedure, while executing
stored procedure it gives error like conversion failed varchar to data
type int
**
ALTER PROCEDURE [dbo].[SUMMARY_DETAILS_PROJECT_SEARCH_MAP]
#PROJECT_CAT INT=NULL,
#PROJECT_TYPE INT=NULL,
#ADDRESS VARCHAR(150)=NULL,
#MIN_PRICE INT=NULL,
#MAX_PRICE INT=NULL,
#BEDROOM VARCHAR(150)=NULL
AS
CREATE TABLE #TEMP_MAP
(
SN INT IDENTITY,
PROJECT_ID INT,
PROJECT_NAME VARCHAR(100),
LAT VARCHAR(50),
LONG VARCHAR(50),
PROJECT_LOC VARCHAR(150),
MIN_PRICE VARCHAR(100),
MAX_PRICE VARCHAR(100),
PROJECT_IMAGE VARCHAR(250)
)
DECLARE #SQL NVARCHAR(MAX),#PARAMETER_LIST NVARCHAR(MAX)
DECLARE #COUNT_ZONE INT
DECLARE #COUNT_CITY INT
SELECT #COUNT_ZONE= (SELECT COUNT(*) FROM ZONE_MASTER WHERE ZONE_NAME LIKE #ADDRESS + '%')
SELECT #SQL = ('SELECT PROJECT_ID FROM PROJECTS WHERE STATUS=1')
IF(#PROJECT_CAT !=0)
SELECT #SQL = #SQL+' AND PROJECT_CAT_ID=#XP_PROJECT_CAT'
IF(#PROJECT_TYPE !=0)
SELECT #SQL = #SQL+' AND PROJECT_TYPE_ID=#XP_PROJECT_TYPE'
IF(#COUNT_ZONE !=0)
SELECT #SQL = #SQL+' AND ZONE_ID IN (SELECT ZONE_ID FROM ZONE_MASTER WHERE ZONE_NAME LIKE '''+#ADDRESS+''' + ''%'')'
ELSE
SELECT #SQL = #SQL+' AND BLOCK_ID IN (SELECT BLOCK_ID FROM BLOCK_MASTER WHERE BLOCK_NAME LIKE '''+#ADDRESS+''' + ''%'')'
IF(#MIN_PRICE !=0)
SELECT #SQL = #SQL+' AND MIN_ID >=#XP_MIN_PRICE'
IF(#MAX_PRICE !=0)
SELECT #SQL = #SQL+' AND MAX_ID <=#XP_MAX_PRICE'
IF(#BEDROOM !='')
SELECT #SQL = #SQL+' AND BEDROOM=#XP_BEDROOM'
SELECT #SQL = #SQL + ' ORDER BY PROJECT_ENTRY_DATE DESC '
SELECT #PARAMETER_LIST = '#XP_PROJECT_CAT INT,#XP_PROJECT_TYPE INT,#XP_MIN_PRICE INT,#XP_MAX_PRICE INT,#XP_BEDROOM VARCHAR(100)'
INSERT INTO #TEMP_MAP (PROJECT_ID)
EXEC SP_EXECUTESQL #SQL,#PARAMETER_LIST,'#XP_PROJECT_CAT','#XP_PROJECT_TYPE','#XP_MIN_PRICE','#XP_MAX_PRICE','#XP_BEDROOM'
PRINT #SQL
UPDATE #TEMP_MAP SET
PROJECT_NAME = P.PROJECT_NAME,
LAT = P.PROJECT_LAT,
LONG = P.PROJECT_LONG,
PROJECT_LOC = P.PROJECT_LOC,
MIN_PRICE = P.MAX_PRICE,
MAX_PRICE = P.MIN_PRICE,
PROJECT_IMAGE = './UploadImage/Upload_Project/' + P.PROJECT_NAME +'/' + 'Google' + '/' + [IMG1]
FROM Projects P WHERE P.PROJECT_ID=#TEMP_MAP.PROJECT_ID
SELECT * FROM #TEMP_MAP
DROP TABLE #TEMP_MAP
It is because you are putting single quotes around the values you are passing to sp_executesql, e.g:
EXEC SP_EXECUTESQL #SQL,#PARAMETER_LIST,'#XP_PROJECT_CAT'
Here you are not passing the integer value of #XP_PROJECT_CAT, but you are passing the string '#XP_PROJECT_CAT', and the procedure is expecting an int.
As an aside, I am not sure why you have opted for parameterising everything apart from address? Surely it would make sense to parameterise this too - e.g.
IF(#COUNT_ZONE !=0)
SELECT #SQL = #SQL+' AND ZONE_ID IN (SELECT ZONE_ID
FROM ZONE_MASTER
WHERE ZONE_NAME LIKE #ADDRESS + ''%'')'
ELSE
SELECT #SQL = #SQL+' AND BLOCK_ID IN (SELECT BLOCK_ID
FROM BLOCK_MASTER
WHERE BLOCK_NAME LIKE #ADDRESS + ''%'')'
Then add #Address as a parameter to sp_executesql
Let's say I have two tables Company (almost 60K records) and Position (almost 600K records)
Company table:
CompanyID INT --PRIMARY KEY
CompanyName NVARCHAR(100)
CompanyType INT --Just can be (1,2,3,4,5,6)
Position table:
PositionID INT --Primary key
PositionName NVARCHAR(100)
CompanyID INT --FK point to Company Table
WorkExperience INT --Just can be (1,2,3,4,5,6,7,8)
WorkType INT --Just can be (1,2)
CreateTime datetime
UpdateTime datetime
I have created a NONCLUSTERED INDEX on the Company table:
CREATE NONCLUSTERED INDEX [IX_1] ON [dbo].[Company]
(
[CompanyKind] ASC
)
INCLUDE ( [CompanyName]) ON [PRIMARY]
GO
And I have created two NONCLUSTERED INDICES ON the Position table also:
CREATE NONCLUSTERED INDEX [IX_6] ON [dbo].[Position]
(
[CompanyID] ASC
)ON [PRIMARY]
CREATE NONCLUSTERED INDEX [IX_8] ON [dbo].[Position]
(
[UpdateTime] ASC
) ON [PRIMARY]
My paging stored procedure looks like this:
ALTER PROC [dbo].[spIndexJobList]
#KeyWord NVARCHAR(50) ,
#WorkExperience INT ,
#WorkType INT ,
#CompanyType INT ,
#PageSize INT ,
#PageNumber INT
--#RowCount INT OUTPUT
AS
DECLARE #RowStart INT
DECLARE #RowEnd INT
DECLARE #SQL NVARCHAR(4000)
DECLARE #ParamDefinition NVARCHAR(2000)
SET #SQL = N'SELECT C.CompanyID,C.CompanyName,P.PositionName,P.PositionID,P.UpdateTime, Row_number() OVER (ORDER BY P.UpdateTime DESC) AS RowNumber FROM Company C INNER JOIN Position P ON C.CompanyID=P.CompanyID WHERE 1=1 '
IF #KeyWord!=''
SET #SQL = #SQL + ' AND PositionName LIKE #KeyWord'
IF #WorkExperience !=0
SET #SQL = #SQL + ' AND P.WorkExperience=#WorkExperience'
IF #CompanyType != 0
SET #SQL = #SQL + ' AND C.CompanyType=#CompanyType'
IF #WorkType !=0
SET #SQL = #SQL + ' AND P.WorkType=#WorkType'
SET #ParamDefinition = ' #KeyWord NVarchar(50),
#WorkExperience INT,
#WorkType INT,
#CompanyType INT,
#PageSize INT,
#PageNumber INT'
IF #PageNumber > 0
BEGIN
SET #PageNumber = #PageNumber - 1
SET #RowStart = #PageSize * #PageNumber + 1 ;
SET #RowEnd = #RowStart + #PageSize - 1 ;
SET #SQL = '
WITH AllJobs
AS (' + #SQL
+ ')
SELECT *,(SELECT Count(RowNumber) FROM AllJobs) AS TotalRows FROM AllJobs WHERE RowNumber >='
+ STR(#RowStart) + ' AND RowNumber <= ' + STR(#RowEnd) + ''
EXECUTE sp_Executesql #SQL, #ParamDefinition,
#KeyWord, #WorkExperience,#WorkType,
#CompanyType, #PageSize, #PageNumber
END
My call statement is this:
SET STATISTICS IO ON
DECLARE #return_value int
EXEC #return_value = [dbo].[spIndexJobList]
#KeyWord='',
#WorkExperience = 3,
#CompanyType = 2,
#WorkType =1,
#PageSize = 30,
#PageNumber =2000
SELECT 'Return Value' = #return_value
GO
SET STATISTICS IO OFF
//-----------------------------------------------------------------------
(30 row(s) affected)
Table 'Company'. Scan count 3, logical reads 632, physical reads 0
Table 'Position'. Scan count 3, logical reads 4865, physical reads 0
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0
//-----------------------------------------------------------------------
The execute plan prompt missing index on(WorkExperience,WorkType).
But after created index on (WorkExperience,WorkType) query slower.
Anyone give me some suggestions will very appreciate. Sorry for my bad english!
DDL:
Company table:
CompanyID INT NOT NULL PK
CompanyName NVARCHAR(100) NOT NULL
CompanyType TINYINT NOT NULL
Position table:
PositionID INT NOT NULL PK
PositionName NVARCHAR(100) NOT NULL
CompanyID INT NOT NULL
WorkExperience TINYINT NOT NULL
WorkType TINYINT NOT NULL
CreateTime SMALLDATETIME
UpdateTime SMALLDATETIME
Index:
CREATE NONCLUSTERED INDEX IX_Position
ON Position (WorkExperience, WorkType, PositionName)
INCLUDE (UpdateTime)
SP:
ALTER PROC [dbo].[spIndexJobList]
#KeyWord NVARCHAR(50)
, #WorkExperience TINYINT
, #WorkType TINYINT
, #CompanyType INT
, #PageSize INT
, #PageNumber INT
AS BEGIN
SET NOCOUNT ON;
IF #PageNumber > 0 BEGIN
DECLARE
#RowStart INT
, #RowEnd INT
, #SQL NVARCHAR(4000)
, #ParamDefinition NVARCHAR(500)
SELECT #SQL = N'
SELECT
c.CompanyID
, c.CompanyName
, p.PositionName
, p.PositionID
, p.UpdateTime
, RowNumber = ROW_NUMBER() OVER (ORDER BY p.UpdateTime DESC)
FROM dbo.Company c
JOIN dbo.Position p ON c.CompanyID = p.CompanyID
WHERE 1=1 '
+ CASE WHEN #KeyWord != '' THEN ' AND PositionName LIKE #KeyWord' ELSE '' END
+ CASE WHEN #WorkExperience != 0 THEN ' AND p.WorkExperience = #WorkExperience' ELSE '' END
+ CASE WHEN #CompanyType != 0 THEN ' AND c.CompanyType = #CompanyType' ELSE '' END
+ CASE WHEN #WorkType != 0 THEN ' AND p.WorkType = #WorkType' ELSE '' END
SET #ParamDefinition = '#KeyWord NVARCHAR(50),
#WorkExperience INT,
#WorkType INT,
#CompanyType INT,
#PageSize INT,
#PageNumber INT'
SELECT
#PageNumber = #PageNumber - 1
, #RowStart = #PageSize * #PageNumber + 1
, #RowEnd = #RowStart + #PageSize - 1
, #SQL = '
WITH AllJobs AS (' + #SQL + ')
SELECT *
FROM AllJobs a
CROSS JOIN (
SELECT TotalRows = Count(RowNumber)
FROM AllJobs
) t
WHERE a.RowNumber BETWEEN ' + STR(#RowStart) + ' AND ' + STR(#RowEnd)
EXEC sys.sp_executesql
#SQL,
#ParamDefinition,
#KeyWord,
#WorkExperience,
#WorkType,
#CompanyType,
#PageSize,
#PageNumber
END
END
Manual:
Bad habits to kick : choosing the wrong data type
I would create a nonclustered index on Position like so:
CREATE NONCLUSTERED INDEX IX_Position_WorkExperienceWorkTypePositionName
ON Position (WorkExperience, WorkType, PositionName)
INCLUDE (PositionID, UpdateTime)
Also I would create another non-clustered index on Company like below:
CREATE NONCLUSTERED INDEX IX_Company_CompanyId_Type
ON Company(CompanyId,CompanyType)
Because the where clause include "C.CompanyType=#CompanyType", without this index, this condition caused the table scan Company.
With this index, it's index seek.
Company.CompanyID and Position.CompanyID should be indexed, and you might as well take advantage of CLUSTER indexing these two columns so that the rows get physically ordered in sync with their indexes. This should provide significant performance improvement.