I want to optimize this SP, anyone have some idea how I can do that? Thanks in advance.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[Members] (
#StartTime datetime = null
, #EndTime datetime = null
, #CustomerEmail nvarchar(255) = null
, #CustomerName nvarchar(255) = null
, #ShippingMethod nvarchar(255) = null
, #MemberOrderStatusPending int = null
, #MemberOrderProcessing int = null
, #MemberOrderComplete int = null
, #MemberOrderStatusCancelled int = null
, #MemberOrderStatusCancelledDiscontinued int = null
, #MemberOrderStatusCancelledCustomerRequest int = null
, #MemberOrderStatusCancelledPendingNeverPaid int = null
)
AS
BEGIN
SET NOCOUNT ON
SELECT DISTINCT o.OrderID
, o.OrderTotal
, o.BillingFirstName + ' ' + o.BillingLastName AS CustomerName
, o.CreatedOn AS CreatedOn
FROM Order o
WHERE ( o.CreatedOn > #StartTime OR #StartTime IS NULL )
AND ( o.CreatedOn < #EndTime OR #EndTime IS NULL )
AND ( o.ShippingEmail = #CustomerEmail OR #CustomerEmail IS NULL)
AND ( o.BillingFirstName + ' ' + o.BillingLastName = #CustomerName OR #CustomerName IS NULL )
AND ( o.ShippingFirstName + ' ' + o.ShippingLastName = #CustomerName OR #CustomerName IS NULL )
AND ( o.ShippingMethod = #ShippingMethod OR #ShippingMethod IS NULL )
AND ( o.OrderStatusID = #MemberOrderProcessing
OR o.OrderStatusID = #MemberOrderProcessing
OR o.OrderStatusID = #MemberOrderComplete
OR o.OrderStatusID = #MemberOrderStatusCancelled
OR o.OrderStatusID = #MemberOrderStatusCancelledDiscontinued
OR o.OrderStatusID = #MemberOrderStatusCancelledCustomerRequest
OR o.OrderStatusID = #MemberOrderStatusCancelledPendingNeverPaid
OR #MemberOrderProcessing IS NULL
OR #MemberOrderProcessing IS NULL
OR #MemberOrderComplete IS NULL
OR #MemberOrderStatusCancelled IS NULL
OR #MemberOrderStatusCancelledDiscontinued IS NULL
OR #MemberOrderStatusCancelledCustomerRequest IS NULL
OR #MemberOrderStatusCancelledPendingNeverPaid IS NULL )
ORDER BY
o.OrderID
END
When you have that many OR conditions performance is bound to suffer (not to mention that this would lead to parameter sniffing). I would highly recommend using Dynamic SQL here. Something like this,
DECLARE #query VARCHAR(MAX)
SET #query =
'SELECT DISTINCT o.OrderID, o.OrderTotal, o.BillingFirstName + ' ' + o.BillingLastName AS CustomerName, o.CreatedOn AS CreatedOn FROM Order o
WHERE 1=1 '
IF #StartTime IS NOT NULL
SET #query = #query + ' AND o.CreatedOn > #StartTime'
IF #EndTime IS NOT NULL
SET #query = #query + ' AND o.CreatedOn < #EndTime'
IF #CustomerEmail IS NOT NULL
SET #query = #query + ' AND o.ShippingEmail = #CustomerEmail'
......
......
exec sp_executesql #query,
N'#StartTime DATETIME,
#EndTime DATETIME,
...<other param definitions>',
#StartTime,
#EndTime,
.. <other param values>
best source for dynamic search conditions:
Dynamic Search Conditions in T-SQL by Erland Sommarskog
there are a lot of subtle implications on how you do this as to if an index can be used or not. If you are on the proper release of SQL Server 2008 you can just add OPTION (RECOMPILE) to the query and the local variable's value at run time is used for the optimizations.
Consider this, OPTION (RECOMPILE) will take this code (where no index can be used with this mess of ORs):
WHERE
(#search1 IS NULL or Column1=#Search1)
AND (#search2 IS NULL or Column2=#Search2)
AND (#search3 IS NULL or Column3=#Search3)
and optimize it at run time to be (provided that only #Search2 was passed in with a value):
WHERE
Column2=#Search2
and an index can be used (if you have one defined on Column2)
if you are not on the needed release of SQL Server 2008, the linked article offers many methods with pros and cons for each. for example, if you can determine a min and a max possible range for your search column, and the search column is NOT NULL, then you can do better than the (#Search IS NULL OR Col=#Search), see this area of the above linked article. However you should read the entire article, there are so many variations that depend on your situation, you really need to learn multiple approaches and when to use them.
IF the OrderStatusID is a bit field, following might work
SELECT DISTINCT o.OrderID
, o.OrderTotal
, o.BillingFirstName + ' ' + o.BillingLastName AS CustomerName
, o.CreatedOn AS CreatedOn
FROM Order o
WHERE ( o.CreatedOn > COALESCE( #StartTime, '01-01-1899' ))
AND ( o.CreatedOn < COALESCE( #EndTime, '01-01-2099' ))
AND ( o.BillingFirstName + ' ' + o.BillingLastName = COALESCE( #CustomerName, o.BillingFirstName + ' ' + o.BillingLastName ))
AND ( o.ShippingFirstName + ' ' + o.ShippingLastName = COALESCE (#CustomerName, o.ShippingFirstName + ' ' + o.ShippingLastName ))
AND ( o.ShippingEmail = COALESCE(#CustomerEmail, o.ShippingEmail )
AND ( o.ShippingMethod = COALESCE ( #ShippingMethod, o.ShippingMethod )
AND ( o.OrderStatusID & (
COALESCE ( #MemberOrderProcessing, 1 )
| COALESCE ( #MemberOrderComplete, 2 )
| COALESCE ( #MemberOrderStatusCancelled , 4 )
| COALESCE ( #MemberOrderStatusCancelledDiscontinued , 8 )
| COALESCE ( #MemberOrderStatusCancelledCustomerRequest , 16 )
| COALESCE ( #MemberOrderStatusCancelledPendingNeverPaid , 32 )
) >= 1
)
ORDER BY
o.OrderID
Related
I write this query in SQL Server 2016:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[s2_GetReceivedDocumentsCount]
#_Username NVARCHAR(MAX),
#_SearchText NVARCHAR(MAX),
#_States NVARCHAR(MAX),
#_Senders NVARCHAR(MAX),
#_Date1 NVARCHAR(MAX),
#_Date2 NVARCHAR(MAX),
#_Filter1ID NVARCHAR(MAX),
#_Filter1Value NVARCHAR(MAX)
AS
BEGIN
--https://blogs.technet.microsoft.com/mdegre/2011/11/06/what-is-parameter-sniffing/
DECLARE #Username NVARCHAR(MAX)
DECLARE #Fild BIT
DECLARE #SearchText NVARCHAR(MAX)
DECLARE #States NVARCHAR(MAX)
DECLARE #Senders NVARCHAR(MAX)
DECLARE #Date1 NVARCHAR(MAX)
DECLARE #Date2 NVARCHAR(MAX)
DECLARE #Filter1ID NVARCHAR(MAX)
DECLARE #Filter1Value NVARCHAR(MAX)
SELECT
#Username = #_Username,
#SearchText = #_SearchText,
#States = #_States,
#Senders = #_Senders,
#Date1 = #_Date1,
#Date2 = #_Date2,
#Filter1ID = #_Filter1ID,
#Filter1Value = #_Filter1Value
SELECT #SearchText = LTRIM(RTRIM(IsNull(#SearchText, '')))
SELECT #Filter1ID = LTRIM(RTRIM(IsNull(#Filter1ID, '')))
SELECT #Filter1Value = LTRIM(RTRIM(IsNull(#Filter1Value, '')))
DECLARE #PersonalPostID INT = NULL
SELECT #PersonalPostID = p.PostID
FROM Person pr
JOIN PersonPost pp ON pp.PersonID = pr.PersonID
JOIN Post p ON p.PostID = pp.PostID
WHERE pr.Username = #Username
AND p.IsPersonalPost = 1
DECLARE #independentPostExists BIT = CASE
WHEN EXISTS (SELECT 1 FROM Post t
WHERE t.Independent = 1 AND t.PostID > 0)
THEN 1
ELSE 0
END
DECLARE #temp0 TABLE (
DocumentID int
, Likeness int
, ParentScrutinyID int
)
;With AllPost
As
(
Select pp.PostID
From
PersonPost pp
Join Person prs On prs.PersonID = pp.PersonID
Where prs.Username = #Username
Union
Select [type].PostID
From
Post [type]
Join Post p On p.TypeID = [type].PostID
Join PersonPost pp On pp.PostID = p.PostID
Join Person prs On prs.PersonID = pp.PersonID
Where prs.Username = #Username
)
,
SplitSearchText
AS
(
Select * From dbo._1001_Split(dbo.ReplaceYK(#SearchText),N'')
),
Temp0
AS
(
Select Distinct
s.DocumentID
, s.Code
, s2_Scrutiny.ParentScrutinyID
From
s2_Document s
Join s2_State state On state.StateID = s.StateID
Join Post sender On sender.PostID = s.SenderID
Join s2_Scrutiny On
s2_Scrutiny.DocumentID = s.DocumentID
And s2_Scrutiny.IsActive = 1
And s2_Scrutiny.ReferenceID not in (-10, -20)
Cross Join AllPost
Join s2_Producer On s2_Producer.DocumentID = s.DocumentID
Join PersonPost producerPost On producerPost.PostID = s2_Producer.PostID
Join Person producerPerson On producerPerson.PersonID = producerPost.PersonID
Where
1 = 1
And (#States = '' Or (N',' + #States + N',') Like (N'%,' + Cast(s.StateID as nvarchar(max)) + ',%'))
And (#Senders = '' Or (N',' + #Senders + N',') Like (N'%,' + Cast(s.SenderID as nvarchar(max)) + ',%'))
And (#Date1 = '' Or s.RegistrationDate >= #Date1)
And (#Date2 = '' Or s.RegistrationDate <= #Date2)
And (#Filter1ID = ''
Or Exists(
Select 1
From
s2_FieldValue fv
Join s2_Field f On f.FieldID = fv.FieldID
Where
fv.DocumentID = s.DocumentID
And fv.FieldID = #Filter1ID
And (
(f.FieldTypeID in (0, 5/*فیلد محاسباتی*/) And fv.[Value] = #Filter1Value)
Or (f.FieldTypeID = 3 And Cast(fv.[FieldOptionID] as nvarchar(max)) = #Filter1Value)
Or (f.FieldTypeID in(1,2,4))
)
))
--پیشنهاد به پست یا نوع پستی که این شخص حائز آن است، ارجاع شده است
And AllPost.PostID = s2_Scrutiny.ReferenceID
), Temp1
AS
(
Select Distinct
s.DocumentID
,Likeness = 99999999
From Temp0 s
Where #SearchText != '' And #SearchText = ISNULL(s.Code, s.DocumentID)
Union
Select Distinct
s.DocumentID
,Likeness = SUM(ts.[Length])
From
Temp0 s
Join s2_TextSegment ts On
ts.TableName = N's2_Document'
And ts.FieldName = N'Subject'
And ts.RecordID = s.DocumentID
Where #SearchText != '' And #SearchText != ISNULL(s.Code, s.DocumentID)
Group by s.DocumentID
Union
Select Distinct
s.DocumentID
,Likeness = 1
From Temp0 s
Where #SearchText = ''
)
, Temp2
AS
(
Select t0.*, t1.Likeness
From
Temp0 t0
Join Temp1 t1 On t0.DocumentID = t1.DocumentID
)
Insert Into #temp0 (DocumentID, Likeness, ParentScrutinyID)
Select DocumentID, Likeness, ParentScrutinyID From Temp2
DECLARE #temp1 TABLE (
DocumentID int
, Likeness int
)
If #independentPostExists = 0
Begin
Insert Into #temp1 (DocumentID, Likeness)
Select
t.DocumentID
, t.Likeness
From
#temp0 t
End
ELSE
Begin--حوزه مستقلی تعریف شده باشد
--انتقال حوزه فعال باشد
Insert Into #temp1 (DocumentID, Likeness)
Select
t.DocumentID
, t.Likeness
From
#temp0 t
Join s2_Scrutiny parentScrutiny On parentScrutiny.ScrutinyID = t.ParentScrutinyID
Join s2_ScrutinyItem sci On sci.ScrutinyItemID = parentScrutiny.ScrutinyItemID
Where
sci.TransferArea = 1
-- شخص جاری در حوزه ارجاع دهنده باشد
Insert Into #temp1 (DocumentID, Likeness)
Select
t.DocumentID
, t.Likeness
From
#temp0 t
Join s2_Scrutiny parentScrutiny On parentScrutiny.ScrutinyID = t.ParentScrutinyID
Join Temp_SubalternPost tsp1 On tsp1.Subaltern_PostID = parentScrutiny.ScrutinierID
Join Temp_SubalternPost tsp2 On tsp2.Superior_PostID = tsp1.Superior_PostID
Where
tsp1.Superior_NearestIndependent = 1
And tsp2.Subaltern_PostID = #PersonalPostID
--And Not Exists(Select 1 From #temp0 tt Where tt.DocumentID = t.DocumentID)
End
Select Count(Distinct t.DocumentID) From #temp1 t Where Likeness > 0
END--end procedure
GO
This code takes 26 seconds:
exec sp_executesql N'Exec [dbo].[s2_GetReceivedDocumentsCount] #username=N'admin', #Filter1ID=N'12',#Filter1Value=N'17658'
BUT :
I tested this code for another state but returned 22,000 records in 3 seconds
exec sp_executesql N'Exec [dbo].[s2_GetReceivedDocumentsCount] #username=N'admin'
In this code I removed the #Filter1ID=N'12',#Filter1Value=N'17658'
When I remove this #Filter1ID it not enter here:
And (#Filter1ID = ''
Or Exists(
Select 1
From
s2_FieldValue fv
Join s2_Field f On f.FieldID = fv.FieldID
Where
fv.DocumentID = s.DocumentID
And fv.FieldID = #Filter1ID
And (
(f.FieldTypeID in (0, 5/*فیلد محاسباتی*/) And fv.[Value] = #Filter1Value)
Or (f.FieldTypeID = 3 And Cast(fv.[FieldOptionID] as nvarchar(max)) = #Filter1Value)
Or (f.FieldTypeID in(1,2,4))
)
))
Now I'm sure problem is here. But where is it? Where is the problem?
While correlated EXISTS clauses can be a real problem, your overall SP is such a dogs breakfast that I think you should focus on other aspects first:
Do not use LIKE to match a list of numeric values:
(N',' + #States + N',') Like (N'%,' + Cast(s.StateID as nvarchar(max)) + ',%'))
Since you already utilise string splitting function, you should split input value into a table variable of stateIDs (make sure that data type is the same as s.StateID and join it. Do the same for #Senders.
Minimise the use of OR as this kills performance really quickly:
This And (#Date1 = '' Or s.RegistrationDate >= #Date1) should be replaced by:
SET #Date1 = CASE WHEN '' THEN '01-Jan-1753' ELSE #Date1 END and then in your query you can simply have And s.RegistrationDate >= #Date1.
For #Date2 use the maximum value as per DATETIME reference.
Get rid of NVARCHAR( MAX ). Unless you realistically expect input values to be more than 4000 characters, you should use NVARCHAR( 2000 ) or something smaller.
There is a major performance difference between UNION and UNION ALL. Make sure you use UNION ALL unless you need to remove duplicate records. See this
And lastly EXISTS: without fully knowing your table structure and being able to run the query myself I cannot see a way of removing it, such that it will definitely improve performance.
i am using the below query to return rowcount for paging, it works fine but take very long to return, because all of the table have millions of records.
currently its taking 7 sec to return rowcount, can anyone help me in this to return it fast.
i have also tried same query with #table and #table both are slow.
query is
WITH cte_rowcount
AS (SELECT p.policyid
FROM resident (nolock) r
INNER JOIN resident_policy (nolock) rp
ON r.residentid = rp.residentid
INNER JOIN policy (nolock) p
ON p.policyid = rp.policyid
--INNER JOIN PolicySource (NOLOCK) psourse ON p.PolicySourceID = psourse.PolicySourceId
INNER JOIN policy_locations (nolock) pl
ON pl.policyid = p.policyid
INNER JOIN location (nolock) l
ON pl.locationid = l.locationid
--INNER JOIN Policy_Status (NOLOCK) ps ON ps.PolicyStatusId = p.PolicyStatusId
INNER JOIN property (nolock) pr
ON pr.propertyid = l.propertyid
--INNER JOIN dbo.States (NOLOCK) s ON s.StateId = pr.StateId
WHERE r.primary_resident = 0x1
AND ( ( #ResidentFirstName IS NULL )
OR R.firstname LIKE #ResidentFirstName + '%' )
AND ( ( #ResidentLastName IS NULL )
OR R.firstname LIKE #ResidentLastName + '%' )
AND ( #PropertyAddress IS NULL
OR pr.address LIKE #PropertyAddress + '%' )
AND ( #Policynumber IS NULL
OR p.policynumber LIKE #Policynumber + '%' )
AND ( #LocationAddress IS NULL
OR l.address2 LIKE #LocationAddress + '%' )
AND ( #City IS NULL
OR pr.city LIKE #City + '%' )
AND ( #ZipCode IS NULL
OR pr.zipcode = #ZipCode )
AND ( #StateId IS NULL
OR pr.stateid = #StateId )
AND ( #PolicyStatusId IS NULL
OR p.policystatusid = #PolicyStatusId ))
SELECT #rowcount = Count(*)
FROM cte_rowcount
I'd say to look at the indexes, but it probably won't help much, because a) you probably did it already, and b) you can get no seeks with this kind of a query, only scans.
The idea is to get rid of these ORs and allow the optimizer to produce a sound plan.
There are two options.
Don't know which version of SQL Server is in question, but if it's SQL 2008 SP1 CU5 (10.0.2746) or later, or SQL 2008 R2 CU1 (10.50.1702) or later, or anything newer than that, add an option (recompile) to the query. This should produce much better plan, using seeks on relevant indexes.
This will, however, add some recompile overhead to every execution, so maybe the second option is better.
You can rewite the query into dynamic one, and elliminate the NULL parameters before optimizer even see the query. I tried to rewrite your query, don't have your data so can't test it, and there may be some errors in it, but you'll get my intention nevertheless. And I had to guess the datatypes. (BTW, is there a specific reason for SELECT p.policyid?)
Here it is:
declare #qry nvarchar(4000), #prms nvarchar(4000);
set #qry = N'
SELECT count(*)
FROM resident (nolock) r
INNER JOIN resident_policy (nolock) rp
ON r.residentid = rp.residentid
INNER JOIN policy (nolock) p
ON p.policyid = rp.policyid
INNER JOIN policy_locations (nolock) pl
ON pl.policyid = p.policyid
INNER JOIN location (nolock) l
ON pl.locationid = l.locationid
INNER JOIN property (nolock) pr
ON pr.propertyid = l.propertyid
WHERE r.primary_resident = 0x1 '
if #ResidentFirstName IS NOT NULL
set #qry = #qry + ' AND R.firstname LIKE #ResidentFirstName + ''%'''
if #ResidentLastName IS NOT NULL
set #qry = #qry + ' AND R.firstname LIKE #ResidentLastName + ''%'''
if #PropertyAddress IS NOT NULL
set #qry = #qry + ' AND pr.address LIKE #PropertyAddress + ''%'''
if #Policynumber IS NOT NULL
set #qry = #qry + ' AND p.policynumber LIKE #Policynumber + ''%'''
if #LocationAddress IS NOT NULL
set #qry = #qry + ' AND l.address2 LIKE #LocationAddress + ''%'''
if #City IS NOT NULL
set #qry = #qry + ' AND pr.city LIKE #City + ''%'''
if #ZipCode IS NOT NULL
set #qry = #qry + ' AND pr.zipcode = #ZipCode'
if #StateId IS NOT NULL
set #qry = #qry + ' AND pr.stateid = #StateId'
if #PolicyStatusId IS NOT NULL
set #qry = #qry + ' AND p.policystatusid = #PolicyStatusId'
set #prms = N'#PolicyStatusId int, #StateId int, #ZipCode int,
#City varchar(50), #LocationAddress varchar(50), #Policynumber varchar(50),
#PropertyAddress varchar(50), #ResidentLastName varchar(50), #ResidentFirstName varchar(50)'
exec sp_executesql
#qry,
#prms,
#PolicyStatusId = #PolicyStatusId, #StateId = #StateId, #ZipCode = #ZipCode,
#City = #City, #LocationAddress = #LocationAddress,
#Policynumber = #Policynumber, #PropertyAddress = #PropertyAddress,
#ResidentLastName = #ResidentLastName, #ResidentFirstName = #ResidentFirstName
If you chect the execution plan you'll see the index seeks, provided you have nonclustered indexes on WHERE and JOIN columns.
Moreover, the plan will be cached, one for each combination of parameters.
This is hard to answer because with huge bulk of data many things could happen.
In term of join, this should perform well.
If this query is just here to perform a count, then I can just suggest you to do it directly SELECT count('x') without CTE and without (nolock).
SELECT #rowcount = count('x') as rc
FROM
resident r
INNER JOIN resident_policy rp
ON r.residentid = rp.residentid
INNER JOIN policy p
ON p.policyid = rp.policyid
INNER JOIN policy_locations pl
ON pl.policyid = p.policyid
INNER JOIN location l
ON pl.locationid = l.locationid
INNER JOIN property pr
ON pr.propertyid = l.propertyid
WHERE
r.primary_resident = 0x1
AND ( ( #ResidentFirstName IS NULL )
OR R.firstname LIKE #ResidentFirstName + '%' )
AND ( ( #ResidentLastName IS NULL )
OR R.firstname LIKE #ResidentLastName + '%' )
AND ( #PropertyAddress IS NULL
OR pr.address LIKE #PropertyAddress + '%' )
AND ( #Policynumber IS NULL
OR p.policynumber LIKE #Policynumber + '%' )
AND ( #LocationAddress IS NULL
OR l.address2 LIKE #LocationAddress + '%' )
AND ( #City IS NULL
OR pr.city LIKE #City + '%' )
AND ( #ZipCode IS NULL
OR pr.zipcode = #ZipCode )
AND ( #StateId IS NULL
OR pr.stateid = #StateId )
AND ( #PolicyStatusId IS NULL
OR p.policystatusid = #PolicyStatusId )
If this CTE is used for both rowcount and retrieve data from CTE be sure that you are retrieve only data for the page in question (only 20 elements with a ROWCOUNT() as RC and RC > 0 AND RC <= 20)
In database side, you can check if you have indexes for all of your join clause. It looks like there is only PK so they already have indexes. Be sure, you have index on joined columns.
If you continue to have trouble, use "execution plan in real time" fonction to see what the hell is going on.
LIKE condition can be a performance killer depending on the text size and database content. You can think about COLLECTION to store your texts and have some gain on text comparison.
There are some general instructions:
Create Non clustered Index on All of your foreign-key columns
Create Non clustered Index on primary_resident columns
Include Actual Execution Plan when you run your query and see which part is wasting time
Put Statements that are more likely to be false at first
When you run your query SQL server will suggest you some hints, try them too
I have a table called procedure look up which stores medical procedures
and have multiple company table for which i had to calculate the procedure fees so i had created a dynamic query for it
below is the query
declare #TableProviderName varchar(500)
,#SQLQuery1 nvarchar(max)
,#MaxRecordSize Int
,#Name varchar(250) = null
,#code varchar(50) = null
set #Name = 'sug'
set #TableProviderName = 'PRD_Tata_Details'
set #MaxRecordSize = 50
set #SQLQuery1 = '
;WITH CTE_Procedure AS
(
select top (#MaxRecordSize1)
GPL_ID_PK as ProcedureID
,GPL_ProcedureType as ProcedureType
,GPL_Code as ProcedureCode
,coalesce(Name,GPL_Name,null)as Procedurename
,GPL_CurrencyType_FK as CurrencyType
,ISNULL(GPL_Description,''NIL'') as ProcedureDescription
,ISNULL(GPL_PatientInstruction,''NIL'')as PatientInstructions
,GPL_ProcedureCategory_FK as ProcedureCategory
,GPL_CategorySpecialization_FK as ProcedureSpecialization
,coalesce(PatientPayable,GPL_ProcedureFee,0) as PatientPayable
,0 as InsurancePayable
,0 as InsuranceDiscount
,1 as ProcedureCount
,0 as IndBillingStatus
,Case
when GeneralProcedureID is not null then ''Insurance Supported''
else ''Insurance not Supported''
end as InsuranceStatus
,ROW_NUMBER( ) OVER ( ORDER BY GPL_Name ASC) as RowNumber
from
dbo.PRD_GeneralProcedure_Lookup
left join '
+ #TableProviderName +
'
on
GeneralProcedureID = GPL_ID_PK
where
GPL_ProcedureType = #ProcedureType1
and
(#Name1 is null or GPL_Name like %#Name1%)
and
(#code1 is null or GPL_Code like %#code1%)
)
Select
*
from
CTE_Procedure
'
Execute sp_executesql #SQLQuery1, N'#MaxRecordSize1 int, #ProcedureType1 tinyint,#Name1 varchar(250)
, #code varchar(50)' ,#MaxRecordSize1 = #MaxRecordSize, #ProcedureType1 = 1 , #Name1 = #Name, #code1 = #code
but when executing error occurs saying
"Incorrect syntax near '#Name1'"
can anyone help me with that where condition side issue
I think It may have something to do with your like statement and the way you pass the parameter.
Have a look at this question Parameters & Like statement.
#Name1 = "'%yourvalue%'"
I believe there are many StackOverflow posts related to this error, but none seems to have a straightforward solution which I am looking for. I'll be thankful if anyone of you can look into this.
The issue: I am using a dynamic sql stored procedure which uses FundTransfer Database tables in cte expression and then joins with WebbnkDb database.
But, I run into the exception mentioned in the title above. Everything works fine if I remove WITH EXECUTE AS SELF command but unfortunately I can't get rid of it as it is used for some security reasons. Please suggest me solution in easy words.
USE [WebBank]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[usp_naSearchV2_20131504]
#Debug BIT = 0,
#UserName varchar(50)=NULL, --This will be used to potentially limit the results per user & also for logging
#SSN char(9) = NULL,
#FName varchar(25) = NULL,
#LName varchar(30) = NULL,
#dtApplicationStart datetime = NULL,
#dtApplicationEnd datetime = NULL,
#CompanyName varchar(50) = NULL,
#DaysInTask int = NULL, --This will be how many days it's been in the current task...
#AcctNum varchar(11) = NULL,
#BranchNums varchar(1500) = NULL, --This will be passed to an IN. Don't enclose each in single quotes - for example, '45, 145, 1, 15'
#WorkflowID int = NULL, --1 = HSA, 2 = Personal, 3 = SEI
#OriginationID tinyint = NULL, --This comes from the Applicant record.
#QueueID int = NULL,
#TaskStageIDs varchar(500) = NULL, --Will be passed to an IN, so multiple TaskStageIDs can be passed.
#TaskIDs VARCHAR(1500)=NULL,
#DaysAged int = NULL, --Days since application was entered (not including time spent in approved/declined/open states)
#LastActivityStart datetime=NULL,
#LastActivityEnd datetime=NULL,
#SOAApplID int = NULL, --SEI ID
#Market VARCHAR(50) = NULL, --from luAffinityMarket
#IncludeSecondary bit=0,
#IncludeAliasName bit=0,
#EmailTypeIDs varchar(500) = NULL
WITH EXECUTE AS SELF --This is needed because we're using dynamic SQL & don't want to grant access to underlying tables.
AS
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
/*
** New Account - Search.
**
** This will be done in dynamic SQL. The reason is because when searching on multiple optional parameters,
** SQL cannot use indexes without using dynamic SQL. This makes the proc sssssslllllooooooooowwwwwwwwwww (when not using dynamic sql).
** See http://www.sommarskog.se/dyn-search-2005.html
**
** In addition to the basics (name, social, branch, product, "workflow"), also show Task, Queue, Check-Out info, etc
**
*/
/*
I have to create new version of this store procedure since we continue making changes to resolve helpdesk tickets and
for AOT Part 2. Some tables that we are going to use for AOT project part 2 will not be moved to production until 12/05/10.
New version will be called usp_naSearchV2 and will contain new tables for AOT Part 2
*/
--CAST(ROUND(ISNULL(cteAge.Age + 1, 0), 2) AS DECIMAL(8, 2)) AS DaysAged,
DECLARE #SQL nvarchar(max),#paramlist nvarchar(max)
DECLARE #SOASQL nvarchar(MAX)
SET #FName = '%' + #FName + '%'
SET #LName = '%' + #LName + '%'
SET #CompanyName = '%' + #CompanyName + '%'
SELECT #SQL = '
WITH
cteAutoApprove (AcctID, AutoApproved)
AS (
SELECT awt.AcctID, MIN(CAST(awt.autoEnter AS SMALLINT)) AS AutoApproved
FROM dbo.AccountWorkflowTask awt JOIN dbo.WorkflowTask wt ON awt.WorkflowTaskID = wt.WorkflowTaskID
WHERE (wt.TaskID IN (9, 17) AND ReasonIDExit = 1)
OR (wt.TaskID IN (209, 309, 409, 509, 609, 709, 809, 909) AND ReasonIDExit = 40)
--OR ReasonIDExit IN(216,202) OR ReasonIDEnter=215
or(wt.TaskID=201 and ReasonIDExit is NULL) GROUP BY awt.AcctID),
cteAge (AcctID, Age)
AS (SELECT AcctID, SUM(CASE WHEN t.TaskStageID IN (2, 3, 4) OR t.TaskID = 1 THEN 0 '--don''t count Pending Completion, Open, Approved, or Declined in age
+ 'ELSE DATEDIFF(minute, dtEnter, ISNULL(dtExit, GETDATE())) END) / 60 / 24.0 Age
FROM dbo.AccountWorkflowTask awt JOIN WorkflowTask wt ON awt.WorkflowTaskID = wt.WorkflowTaskID JOIN Task t ON wt.TaskID = t.TaskID
GROUP BY AcctID),
**cteFundingStatus(AcctID,FundingStatus,SourceAccountTypeDescription)
AS
(SELECT TransferStaging.AcctID,luTransferStatus.TransferStatusDesc, luAcctType.AcctTypeDesc from
FundsTransfer.dbo.TransferStaging
JOIN FundsTransfer.dbo.luTransferType ON luTransferType.TransferTypeID = TransferStaging.TransferTypeID
JOIN FundsTransfer.dbo.luAcctType ON luTransferType.SourceAcctTypeID = luAcctType.AcctTypeID
JOIN FundsTransfer.dbo.luTransferStatus ON luTransferStatus.TransferStatusID = TransferStaging.TransferStatusID),**
cteFulfillment(AcctID, Request, TemplateName)
AS
(SELECT ful.AcctID, CAST(Request AS NVARCHAR(max))Request, lt.TemplateName FROM dbo.fulfillment ful left join LetterRequest lr on lr.LetterID = ful.LetterID
LEFT JOIN luLetterTemplate lt ON lt.TemplateID = lr.TemplateID
WHERE (Request IS NOT NULL OR ful.LetterID IS NOT NULL) AND FulfillmentID=(SELECT MAX(FulfillmentID) FROM fulfillment sub WHERE ful.AcctID=sub.AcctID AND (Request IS NOT NULL OR LetterID IS NOT NULL)) ),
cteNote(AcctID,userEntered,dtEntered,Note,NoteReasonDesc,ReasonCode,NoteReasonID)
as
(SELECT AcctID,userEntered,dtEntered,Note,NoteReasonDesc,ReasonCode,n.NoteReasonID FROM note n JOIN
dbo.luNoteReason lu ON lu.NoteReasonID=n.NoteReasonID WHERE '
IF #EmailTypeIDs IS NOT NULL
SELECT #SQL=#SQL+' n.NoteReasonID IN (' + #EmailTypeIDs + ') AND '
SELECT #SQL=#SQL+ ' dtEntered=(SELECT MAX(dtEntered)FROM note sub WHERE sub.AcctId=n.AcctID '
IF #EmailTypeIDs IS NOT NULL
SELECT #SQL=#SQL+ ' AND sub.NoteReasonID IN (' + #EmailTypeIDs + ')'
SELECT #SQL=#SQL+')) '
SELECT #SQL=#SQL+'SELECT a.ApplID, acct.AcctID, acct.dtApplication, ai.FName, ai.MName, ai.LName, ai.SSN, a.Email, ao.CompanyName,'
SELECT #SQL=#SQL+'ao.DBAName, ao.TaxID, acct.AcctNum, acct.AcctAffinityNum, luA.AffinityNum, luA.AffinityName, t.TaskDesc, awt.dtEnter,'
SELECT #SQL=#SQL+'DATEDIFF(day, awt.dtEnter, GETDATE()) + 1 DaysInTask, q.QueueDesc, w.WorkflowID, w.WorkflowDesc,'
SELECT #SQL=#SQL+'luO.OriginationID, luO.OriginationDesc, aco.dtCheckOut, aco.UserCheckOut, aco.GUIDCheckout, lts.TaskStageDesc,'
SELECT #SQL=#SQL+'DATEDIFF(day, acct.dtApplication, GETDATE()) + 1 DaysAgedOld,CAST(ROUND(ISNULL(cteAge.Age + 1, 0), 2) AS int) AS DaysAged,'
SELECT #SQL=#SQL+'asa.SOAApplID, case when (w.WorkflowID=1 and luO.OriginationID=4) then ''Low''when luO.OriginationID=9 then ''Low'''
SELECT #SQL=#SQL+'else''High'' end as RiskType, awt.userEnter, awt.dtEnter, case when cteAutoApprove.AutoApproved=1 then ''Automated'''
SELECT #SQL=#SQL+'when cteAutoApprove.AutoApproved=0 then ''Manual'' else '''' end as DecisionType,acctLam.Market,ful.Request,ful.TemplateName,fun.SourceAccountTypeDescription,fun.FundingStatus, acct.BrokerCode,
COALESCE(ai.SSN, ao.TAXID) as TIN, case when bup.BusPurposeDesc like ''%Other%'' then ao.BusPurposeOther else bup.BusPurposeDesc end as BusPurpose
,note.Note,note.NoteReasonDesc,note.ReasonCode,aa.RelationshipCode,luRel.RelationshipCodeDesc, Addr.Address1, Addr.Address2, Addr.City, Addr.State, Addr.Zip FROM dbo.Applicant a JOIN dbo.APPLICANTACCOUNT aa ON a.ApplID = aa.ApplID '
IF #IncludeSecondary=0
SELECT #SQL=#SQL+' AND aa.RelationshipCode = ''000'' '
SELECT #SQL=#SQL+'LEFT JOIN dbo.ApplicantIndiv ai ON a.ApplID = ai.ApplID LEFT JOIN dbo.ApplicantOrg ao ON a.ApplID = ao.ApplID JOIN dbo.AFFINITYGROUP ag ON a.AffGroupID = ag.AffGroupID JOIN dbo.luAffinity luA ON ag.AffinityID = luA.AffinityID
JOIN dbo.Account acct ON aa.AcctID = acct.AcctID JOIN dbo.AccountWorkflowTask awt ON acct.AcctID = awt.AcctID AND awt.dtExit IS NULL --join to current AccountWorkflowTask
JOIN dbo.WorkflowTask wt ON awt.WorkflowTaskID = wt.WorkflowTaskID JOIN dbo.Task t ON wt.TaskID = t.TaskID
JOIN dbo.Workflow w ON wt.WorkflowID = w.WorkflowID JOIN dbo.luTaskStage lts ON t.TaskStageID = lts.TaskStageID
LEFT JOIN dbo.Queue q ON t.QueueID = q.QueueID LEFT JOIN dbo.luOrigination luO on a.OriginationID = luO.OriginationID
LEFT JOIN dbo.accountCheckOut aco ON acct.AcctID = aco.AcctID AND aco.dtCheckIn IS NULL LEFT JOIN AccountSOAApplication asa ON acct.AcctID = asa.AcctID
LEFT JOIN cteAutoApprove on cteAutoApprove.AcctID = acct.AcctID LEFT JOIN cteAge ON cteAge.AcctID = acct.AcctID
LEFT JOIN luAffinityMarket lam ON CAST(luA.AffinityNum AS INT) = CAST(lam.BRNCH_NBR AS INT) LEFT JOIN luAffinityMarket acctLam ON acct.AcctAffinityNum = CAST(acctLam.BRNCH_NBR AS INT)
LEFT JOIN cteFulfillment ful on acct.AcctID=ful.AcctID
left Join **cteFundingStatus** fun on fun.AcctID=acct.AcctID
left Join luBusPurpose bup on bup.BusPurposeID=ao.BusPurposeID
Left join cteNote note on acct.AcctID=note.AcctID
left join luRelationshipCode luRel on aa.RelationshipCode=luRel.RelationshipCode
LEFT JOIN Address Addr ON Addr.ApplID = aa.ApplID AND Addr.AddrTypeID = 1
WHERE 1 = 1 ' --this is in here so that the following statements in the WHERE clause can start with "AND (...)".
-- IF #debug = 1 PRINT LEN(#SQL) v_AOTInitialAccountFunding
--SELECT #SQL = REPLACE(#SQL, CHAR(9), '') --remove tabs to save string size
IF #debug = 1 PRINT LEN(#SQL)
IF #SSN IS NOT NULL
SELECT #sql = #sql + ' AND (ai.SSN = #xSSN OR REPLACE(ao.TaxID, ''-'', '''') = #xSSN)'
IF #IncludeAliasName <>1 AND #FName IS NOT NULL
SELECT #sql = #sql + ' AND (ai.FName LIKE #xFName)'
IF #IncludeAliasName <>1 AND #LName IS NOT NULL
SELECT #sql = #sql + ' AND (ai.LName LIKE #xLName)'
IF #IncludeAliasName <>0 AND #FName IS NOT NULL
SELECT #sql = #sql + ' AND (ai.AliasFName LIKE #xFName OR ai.FName LIKE #xFName)'
IF #IncludeAliasName <>0 AND #LName IS NOT NULL
SELECT #sql = #sql + ' AND (ai.AliasLName LIKE #xLName OR ai.LName LIKE #xLName)'
IF #dtApplicationStart IS NOT NULL
SELECT #sql = #sql + ' AND (CONVERT(char(10), acct.dtApplication, 101) >= #xdtApplicationStart)'
IF #dtApplicationEnd IS NOT NULL
SELECT #sql = #sql + ' AND (CONVERT(char(10), acct.dtApplication, 101) <= #xdtApplicationEnd)'
IF #CompanyName IS NOT NULL
SELECT #sql = #sql + ' AND (ao.CompanyName LIKE #xCompanyName)'
IF #DaysInTask IS NOT NULL
SELECT #sql = #sql + ' AND (DATEDIFF(day, awt.dtEnter, GETDATE()) >= #xDaysInTask)'
IF #AcctNum IS NOT NULL
SELECT #sql = #sql + ' AND (acct.AcctNum LIKE #xAcctNum)'
IF #BranchNums IS NOT NULL
--Can't use a parameter of the executesql for the list of affinity numbers.
SELECT #sql = #sql + ' AND (acct.AcctAffinityNum IN (' + #BranchNums + ') OR luA.AffinityNum IN (' + #BranchNums + '))'
IF #WorkflowID IS NOT NULL
SELECT #sql = #sql + ' AND (w.WorkflowID = #xWorkflowID)'
IF #OriginationID IS NOT NULL
SELECT #sql = #sql + ' AND (a.OriginationID = #xOriginationID)'
IF #QueueID IS NOT NULL
SELECT #sql = #sql + ' AND (t.QueueID = #xQueueID)'
IF #TaskStageIDs IS NOT NULL
--Can't use a parameter of the executesql for the list of affinity numbers.
SELECT #sql = #sql + ' AND (lts.TaskStageID IN (' + #TaskStageIDs + '))'
IF #TaskIDs IS NOT NULL
--Can't use a parameter of the executesql for the list of affinity numbers.
SELECT #sql = #sql + ' AND (t.TaskID IN (' + #TaskIDs + '))'
IF #DaysAged IS NOT NULL
SELECT #sql = #sql + ' AND ISNULL(cteAge.Age + 1, 0) <= #xDaysAged'
--SELECT #sql = #sql + ' AND (DATEDIFF(day, acct.dtApplication, GETDATE()) + 1 = #xDaysAged)'
IF #LastActivityStart IS NOT NULL
SELECT #sql = #sql + ' AND (CONVERT(char(10), awt.dtEnter, 101) >= #xLastActivityStart)'
IF #LastActivityEnd IS NOT NULL
SELECT #sql = #sql + ' AND (CONVERT(char(10), awt.dtEnter, 101) <= #xLastActivityEnd)'
IF #Market IS NOT NULL
SELECT #sql = #sql + ' AND (lam.Market = #xMarket OR acctLam.Market = #xMarket)'
IF #EmailTypeIDs IS NOT NULL
SELECT #sql = #sql + ' AND (note.NoteReasonID IN (' + #EmailTypeIDs + '))'
IF #SOAApplID IS NOT NULL
SELECT #sql = #sql + ' AND asa.SOAApplID = #xSOAApplID UNION
SELECT NULL ApplID, NULL AcctID, sa.dtAdded dtApplication, sap.FName, sap.MName, sap.LName, sap.SSN, sap.Email, NULL CompanyName,NULL DBAName,
NULL TaxID, NULL AcctNum, 145 AcctAffinityNum, ''145'' AffinityNum, luA.AffinityName, NULL TaskDesc, NULL dtEnter,
NULL DaysInTask, NULL QueueDesc, NULL WorkflowID, ''SEI Online App'' WorkflowDesc,NULL OriginationID, NULL OriginationDesc, NULL dtCheckOut,
NULL UserCheckOut, NULL GUIDCheckout, NULL TaskStageDesc,
0, DATEDIFF(day, sa.dtAdded, GETDATE()) + 1 DaysAged, sa.SOAApplID,'' '', '' '', '' '' dtEnter, '' ''DecisionType,'' '' Market,
'' ''Request,'' ''SourceAccountTypeDescription,'' ''FundingStatus,'' ''BrokerCode, '' ''TIN,'' ''BusPurpose,'' ''Note,'' ''t,
'' ''t1,'' '' RelationshipCode, '' '' RelationshipCodeDesc FROM SOAApplication sa LEFT JOIN AccountSOAApplication asa
ON sa.SOAApplID = asa.SOAApplID JOIN SOAApplicant sap ON sa.SOAApplID = sap.SOAApplID JOIN luAffinity luA ON luA.AffinityNum = ''145''
WHERE asa.SOAApplID IS NULL AND sa.SOAApplID = #xSOAApplID AND sap.PrimaryContact = 1'
IF #debug = 1
PRINT #sql
IF #debug = 1
PRINT #sql
SELECT #paramlist =
'#xSSN char(9),
#xFName varchar(25),
#xLName varchar(30),
#xdtApplicationStart datetime,
#xdtApplicationEnd datetime,
#xCompanyName varchar(50),
#xDaysInTask int,
#xAcctNum varchar(11),
#xWorkflowID int,
#xOriginationID tinyint,
#xQueueID int,
#xDaysAged int,
#xMarket varchar(50),
#xSOAApplID int,
#xLastActivityStart datetime,
#xLastActivityEnd datetime'
IF #Debug = 1 PRINT LEN(#SQL)
EXEC sp_executesql #sql, #paramlist,
#SSN,
#FName,
#LName,
#dtApplicationStart,
#dtApplicationEnd,
#CompanyName,
#DaysInTask,
#AcctNum,
#WorkflowID,
#OriginationID,
#QueueID,
#DaysAged,
#Market,
#SOAApplID,
#LastActivityStart,
#LastActivityEnd
So when you add EXECUTE AS SELF to a procedure, it's the same as saying "Execute this procedure as though the person who created it is running it". So whoever deploys the procedure (under whatever principal account) is the one that will be the basis for what the procedure uses.
I'm presuming that your deployment strategy is to have an administrator run the CREATE/ALTER steps using the sa account. Your DBAs are probably following best practice and not having the sa account own the databases on the server (and possibly not have read access at all), so you get the security error.
Given all that, in your current situation, you're probably not going to use EXECUTE AS SELF, or at least I suspect so. In terms of when you would want to use it in a more general sense, it's hard to give a blanket answer. Short version is if you have a situation where you ("you" being a principal you can log in as) need to run an object at your level of permissions rather than whatever permissions the caller has.
I have the a query which is union of two queries, the resulting query is returning duplicate records, I don't want duplicate records. I tried using DISTINCT but still getting the same result, can anybody help me fix this query?
I also want to know whether this query is safe from SQL injection... I'll be pasting my query below:
ALTER PROCEDURE [dbo].[sp_GetTrashListWithSorting] --'6dbf9a01-c88f-414d-8dd9-696749258cef', '6dbf9a01-c88f-414d-8dd9-696749258cef','DateTime ASC','0','30'
(
#p_CreatedBy UNIQUEIDENTIFIER,
#p_ToReceipientID UNIQUEIDENTIFIER,
#p_SortExpression NVARCHAR(100),
#p_StartIndex INT,
#p_MaxRows INT
)
AS
SET NOCOUNT ON;
IF LEN(#p_SortExpression) = 0
SET #p_SortExpression ='DateTime DESC'
DECLARE #Sql NVARCHAR(4000)
SET #sql = 'SELECT ID, DateTime, Subject, CreatedBy, ToReceipientID, Status
FROM (SELECT ID,
DateTime,
Subject,
CreatedBy,
ToReceipientID,
Status,
ROW_NUMBER() OVER(ORDER BY '+ #p_SortExpression +') AS Indexing
FROM (SELECT ID,
DateTime,
Subject,
CreatedBy,
ToReceipientID,
SenderStatus AS Status
FROM ComposeMail
WHERE (CreatedBy = #p)
AND (SenderStatus = 7 OR SenderStatus = 8)
UNION
SELECT ID,
DateTime,
Subject,
CreatedBy,
ToReceipientID,
ReceiverStatus As Status
FROM ComposeMail
WHERE (ToReceipientID = #p1)
AND (ReceiverStatus = 7 OR ReceiverStatus = 8)) AS NewDataTable
) AS IndexTable
WHERE
Indexing > #p2 AND Indexing<= (#p2+#p3)'
DECLARE #paramDefinition NVARCHAR(500)
SET #paramDefinition = N'#p UNIQUEIDENTIFIER ,#p1 UNIQUEIDENTIFIER, #p2 INT, #p3 INT'
EXEC sp_executesql #sql, #paramDefinition,
#p = #p_CreatedBy,
#p1 = #p_ToReceipientID,
#p2 = #p_StartIndex ,
#p3 = #p_MaxRows
1) I re-wrote your SQL as:
WITH trash_list AS (
SELECT cm.id,
cm.datetime,
cm.subject,
cm.createdby,
cm.toreceipientid,
cm.senderstatus AS Status
FROM COMPOSEMAIL cm
WHERE cm.createdBy = #p
AND cm.enderStatus IN(7, 8)
UNION
SELECT cm.id,
cm.datetime,
cm.subject,
cm.createdby,
cm.toreceipientid,
cm.receiverstatus AS Status
FROM COMPOSEMAIL cm
WHERE cm.toreceipientid = #p1
AND cm.receiverstatus IN (7, 8))
SELECT t.id,
t.datetime,
t.subject,
t.createdby,
t.toreceipientid,
t.status
FROM (SELECT tl.id,
tl.datetime,
tl.subject,
tl.createdby,
tl.toreceipientid,
tl.status,
ROW_NUMBER() OVER(ORDER BY '+ #p_SortExpression +') AS Indexing
FROM trash_list tl
GROUP BY tl.id,
tl.datetime,
tl.subject,
tl.createdby,
tl.toreceipientid,
tl.status) t
WHERE t.indexing BETWEEN #p2 AND (#p2+#p3)
...but if you still get duplicates, review the logic in the SELECT/UNION in the WITH clause.
Get it to work as normal SQL before turning it into dynamic SQL.
2) The query is not safe from injection attacks because you aren't handling single quotes when users can provide text:
IF LEN(#p_SortExpression)=0
SET #p_SortExpression ='DateTime DESC'
...should be:
IF LEN(#p_SortExpression)=0
SET #p_SortExpression ='DateTime DESC'
ELSE
SET #p_SortExpression = REPLACE(#p_SortExpression, '''', '''''')
You do not need to queries and a union. Instead of these 2 lines (one per subquery)
WHERE (CreatedBy = #p)
WHERE (ToReceipientID = #p1)
do this (in one query)
WHERE CreatedBy IN (#p, #p1)
Like this:
SELECT
ID
, DateTime
, Subject
, CreatedBy
, ToReceipientID
, Status
FROM (
SELECT
ID
, DateTime
, Subject
, CreatedBy
, ToReceipientID
, SenderStatus AS Status
, ROW_NUMBER() OVER (ORDER BY ' + #p_SortExpression + ') AS Indexing
FROM ComposeMail
WHERE CreatedBy IN (#p, #p1)
AND (SenderStatus = 7
OR SenderStatus = 8)
) AS IndexTable
WHERE Indexing > #p2
AND Indexing <= (#p2 + #p3)
HOWEVER I am not sure I understand how you pass in values for #p or #p1