SQL Procedure not showing any value - sql-server

Below is the procedure I created. When I run the query individually I find records in the database but when I execute the procedure it is not fetching any records. where have I gone wrong?
ALTER PROCEDURE [dbo].[GetTransferList]
#date1 datetime='2015-01-01 00:00:00.000',
#date2 datetime='2017-01-01 00:00:00.000',
#shipto varchar(50)=''
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
-- Insert statements for procedure here
DECLARE
#sql NVARCHAR(MAX),
#paramlist NVARCHAR(4000),
#nl CHAR(2) = CHAR(13) + CHAR(10),
#ParamDefinition NVarchar(2000);
SET #sql = 'SELECT A.ItemDescription,A.PurchaseOrderID,A.QuantityReceived,A.Price,A.StoreID,
C.ItemType,C.BinLocation,
B.PONumber,B.ShipTo,B.StoreID
FROM [dbo].[PurchaseOrderEntry] A, [dbo].[PurchaseOrder] B,[dbo].[Item] C
WHERE A.PurchaseOrderID=B.ID AND A.ItemID=C.ID ';
IF (#date1 IS NOT NULL) AND (#date2 IS NOT NULL )
SET #sql += ' AND B.[RequiredDate] between #date1 AND #date2';
IF #shipto IS NOT NULL --!='ALL'
SET #sql += ' AND B.ShipTo = #shipto ';
SET #sql += ' GROUP BY C.BinLocation,A.Price,C.ItemType, B.ID ,A.ItemDescription,
A.PurchaseOrderID,A.QuantityReceived,A.StoreID,B.PONumber,B.ShipTo,B.StoreID'
Set #ParamDefinition =' #shipto varchar(50),
#date1 datetime,
#date2 datetime'
Execute sp_Executesql #sql,
#ParamDefinition,
#shipto,
#date1,
#date2
If ##ERROR <> 0 GoTo ErrorHandler
Set NoCount OFF
Return(0)
ErrorHandler:
Return(##ERROR)
END
the query fetching value is below,
SELECT A.ItemDescription,A.PurchaseOrderID,A.QuantityReceived,A.Price,A.StoreID,
C.ItemType,C.BinLocation,
B.PONumber,B.ShipTo,B.StoreID
FROM [dbo].[PurchaseOrderEntry] A, [dbo].[PurchaseOrder] B,[dbo].[Item] C
WHERE A.PurchaseOrderID=B.ID AND A.ItemID=C.ID
GROUP BY C.BinLocation,A.Price,C.ItemType, B.ID ,A.ItemDescription,
A.PurchaseOrderID,A.QuantityReceived,A.StoreID,B.PONumber,B.ShipTo,B.StoreID

I suspect your biggest problem is #shipto varchar(50)=''. In your proc you then test for null
So this line....
IF #shipto IS NOT NULL
Will not be true if you don't pass anything in it will equal an empty string (unless you actually pass a null value in)
Change this to:
#shipto varchar(50) = null
Then you can test for null as you are doing and this code
IF #shipto IS NOT NULL --!='ALL'
SET #sql += ' AND B.ShipTo = #shipto ';
Will be test true if you do not provide this parameter.
If you ever want to add AND B.ShipTo = '' just pass in a value of '' to #shipto parameter.
However, this bit doesn't need to be dynamic as this will do the same thing
b.shipto = Coalesce(#shipto, B.ShipTo)
The same goes for your date parameters. They will only ever be null if you actually pass in a null value.
As you have no aggregate functions such as SUM, MAX, COUNT etc you don't need the group by.
So my personal preference here would be....
ALTER PROCEDURE [dbo].[GetTransferList]
#date1 datetime=null,
#date2 datetime=null,
#shipto varchar(50) = null
--This will make your parameters optional. IE. You dont have to provide them when you call it
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
IF(#date1 IS NULL) SET #date1 = cast('1899-1-1' as datetime) --This could be anytime in the past thatis prior to any records you hold
IF(#date2 IS NULL) SET #date2 = cast('2100-1-1' as datetime) -- A date well in the future
--You could also set directly as the default values for the parameter but if you do you will have a problem if `null` is passed in.
SELECT A.ItemDescription,A.PurchaseOrderID,A.QuantityReceived,A.Price,A.StoreID,
C.ItemType,C.BinLocation,
B.PONumber,B.ShipTo,B.StoreID
FROM [dbo].[PurchaseOrderEntry] A, [dbo].[PurchaseOrder] B,[dbo].[Item] C
WHERE A.PurchaseOrderID=B.ID AND A.ItemID=C.ID AND B.[RequiredDate] between #date1 AND #date2
AND B.ShipTo = COALESCE(#shipto, b.ShipTo)
If ##ERROR <> 0 GoTo ErrorHandler
Set NoCount OFF
Return(0)
ErrorHandler:
Return(##ERROR)
END
Now you can provide one date (return all records up to a date or all records after a date) or two dates (return all records between dates) or not provide any to see them all. Same for #shipto.

I strongly believe that your date parameter is not matching with the available records, as the query that works fine out side the procedure does not have date condition.
The Date parameters in the proc is marked with default values
if the front end is C# (not sure about other front end code).
The date parameter will be passed with minimum date value or
Null value will be passed if you are not added date parameters in the front end code
But both the case date parameter will have some date values.
Assign the date values to your working query as condition and check.
As asked by Mr.Fred, grouping in your query may not required unless if you are going to have any aggregated fields.

Related

Stored procedure Date From and Date To

I am trying to create a stored procedure for filtering orders. Basically the users have the option of filtering the order by date from and date to. So they can do search via date from, date to or use both if it makes sense?
Anyhow here is my SQL Server stored procedure so far
ALTER PROCEDURE [dbo].[CN_GetOrderItemByCustID]
#CustomerID int,
#OrderItemWRClass varchar(max) = NULL,
#OrderItemSKUName varchar(50) = NULL,
#OrderItemDateFrom Datetime,
#OrderItemDateTo Datetime
AS
BEGIN
SET NOCOUNT ON;
IF DATEDIFF(d, #OrderItemDateFrom, '01/01/1970') = 0
SET #OrderItemDateFrom = null
IF DATEDIFF(d, #OrderItemDateTo, '01/01/1970') = 0
SET #OrderItemDateTo = null
-- Insert statements for procedure here
SELECT
COM_OrderItem.OrderItemID, COM_Order.OrderID,
COM_Order.OrderDate, COM_OrderItem.OrderItemUnitCount,
COM_OrderItem.OrderItemStatus, COM_OrderItem.OrderItemSKUNAME,
COM_OrderItem.OrderItemSKUID
FROM
COM_OrderItem
INNER JOIN
COM_Order ON COM_Order.OrderID = COM_OrderItem.OrderItemOrderID
WHERE
COM_Order.OrderCustomerID = #CustomerID
OR COM_OrderItem.OrderItemWRClass LIKE #OrderItemWRClass + '%'
OR COM_OrderItem.OrderItemSKUName LIKE #OrderItemSKUName + '%'
OR CONVERT(VARCHAR, COM_Order.OrderDate, 120) LIKE #OrderItemDateFrom + '%'
ORDER BY
COM_Order.OrderDate DESC
However I am not sure on how to put the date from (OrderItemDateFrom) and date to (OrderItemDateTo) in the final SQL statement?
Should I be using OR CONVERT(VARCHAR, COM_Order.OrderDate, 120) LIKE #OrderItemDateFrom + '%' -- which gives me an error
Conversion failed when converting date and/or time from character string.
I know in a normal SQL query I would use Between OrderItemDateFrom and OrderItemDateTo
Thanks
Use this logic
ALTER PROCEDURE [dbo].[CN_GetOrderItemByCustID]
-- Add the parameters for the stored procedure here
#CustomerID int,
#OrderItemWRClass varchar(max) = NULL,
#OrderItemSKUName varchar(50) = NULL,
#OrderItemDateFrom Datetime,
#OrderItemDateTo Datetime
AS
BEGIN
SET NOCOUNT ON;
IF DATEDIFF(d,#OrderItemDateFrom,'01/01/1970')=0 SET #OrderItemDateFrom = '01/01/1970';
IF DATEDIFF(d,#OrderItemDateTo,'01/01/1970')=0 SET #OrderItemDateTo = '31/12/2199';
-- Insert statements for procedure here
SELECT COM_OrderItem.OrderItemID, COM_Order.OrderID, COM_Order.OrderDate, COM_OrderItem.OrderItemUnitCount, COM_OrderItem.OrderItemStatus, COM_OrderItem.OrderItemSKUNAME,
COM_OrderItem.OrderItemSKUID
FROM COM_OrderItem
INNER JOIN COM_Order ON COM_Order.OrderID = COM_OrderItem.OrderItemOrderID
WHERE COM_Order.OrderCustomerID = #CustomerID OR COM_OrderItem.OrderItemWRClass LIKE #OrderItemWRClass + '%' OR COM_OrderItem.OrderItemSKUName LIKE #OrderItemSKUName + '%'
OR (COM_OrderDate>=#OrderItemDateFrom && COM_OrderDate<=#OrderItemDateTo )
ORDER BY COM_Order.OrderDate DESC
Try it . It should work.
Your logic can be simplified a little by allowing NULL values for #OrderItemDateFrom and #OrderItemDateTo. Also, if filters values and column values are all DATETIMEs, you should try to compare directly to allow indexes usages (if any applied on the DATETIME column):
ALTER PROCEDURE [dbo].[CN_GetOrderItemByCustID]
#CustomerID int,
#OrderItemWRClass varchar(max) = NULL,
#OrderItemSKUName varchar(50) = NULL,
#OrderItemDateFrom Datetime = NULL, -- TODO: change caller to not provide parameter, or leave it to null
#OrderItemDateTo Datetime = NULL -- TODO: change caller to not provide parameter, or leave it to null
AS
BEGIN
SET NOCOUNT ON;
-- when working with dates try to use an unambiguous format like 'YYYY-MM-DD'
SET #OrderItemDateFrom = ISNULL(#OrderItemDateFrom, '1970-01-01')
-- assign a very large date to act like not provided
-- going one day after to catch DATETIMEs with provided time
SET #OrderItemDateTo = DATEADD(day, 1, ISNULL(#OrderItemDateTo, '3000-01-01'))
-- Insert statements for procedure here
SELECT
COM_OrderItem.OrderItemID, COM_Order.OrderID,
COM_Order.OrderDate, COM_OrderItem.OrderItemUnitCount,
COM_OrderItem.OrderItemStatus, COM_OrderItem.OrderItemSKUNAME,
COM_OrderItem.OrderItemSKUID
FROM COM_OrderItem
INNER JOIN COM_Order ON COM_Order.OrderID = COM_OrderItem.OrderItemOrderID
WHERE COM_Order.OrderCustomerID = #CustomerID
OR COM_OrderItem.OrderItemWRClass LIKE #OrderItemWRClass + '%'
OR COM_OrderItem.OrderItemSKUName LIKE #OrderItemSKUName + '%'
-- between can be used
OR (COM_OrderDate BETWEEN #OrderItemDateFrom AND #OrderItemDateTo)
ORDER BY
COM_Order.OrderDate DESC
END
Another option is to use dynamic SQL and construct it based on parameters values (i.e. insert WHERE condition if filter value is provided). This is particularly useful when filters numbers is relatively low compared to the total number of filters, as ORs are not performance friendly.
NOTE: shouldn't your filters apply in conjuction (i.e. use AND instead of OR)? It would make sense to allow the user to filter by several value in the same time.
ALTER PROCEDURE [dbo].[CN_GetOrderItemByCustID]
#CustomerID int,
#OrderItemWRClass varchar(max) = NULL,
#OrderItemSKUName varchar(50) = NULL,
#OrderItemDateFrom Datetime,
#OrderItemDateTo Datetime
AS
BEGIN
SET NOCOUNT ON;
IF DATEDIFF(d, #OrderItemDateFrom, '01/01/1970') = 0
SET #OrderItemDateFrom = null
IF DATEDIFF(d, #OrderItemDateTo, '01/01/1970') = 0
SET #OrderItemDateTo = null
-- Insert statements for procedure here
SELECT
COM_OrderItem.OrderItemID, COM_Order.OrderID,
COM_Order.OrderDate, COM_OrderItem.OrderItemUnitCount,
COM_OrderItem.OrderItemStatus, COM_OrderItem.OrderItemSKUNAME,
COM_OrderItem.OrderItemSKUID
FROM
COM_OrderItem
INNER JOIN
COM_Order ON COM_Order.OrderID = COM_OrderItem.OrderItemOrderID
WHERE
COM_Order.OrderCustomerID = #CustomerID
OR COM_OrderItem.OrderItemWRClass LIKE #OrderItemWRClass + '%'
OR COM_OrderItem.OrderItemSKUName LIKE #OrderItemSKUName + '%'
OR (#OrderItemDateFrom IS NULL OR COM_Order.OrderDate >=#OrderItemDateFrom)
OR (#OrderItemDateTo IS NULL OR COM_Order.OrderDate <=#OrderItemDateTo)
ORDER BY
COM_Order.OrderDate DESC
You should Try this.
OR (#OrderItemDateFrom IS NULL OR COM_Order.OrderDate >=#OrderItemDateFrom)
OR (#OrderItemDateTo IS NULL OR COM_Order.OrderDate <=#OrderItemDateTo)
Just Edit and try this condition..

Search Stored Procedure (SQL Server) -- Conversion failed when converting date and/or time from character string -- Simple?

I have a stored procedure that I pass 3 variables bankNumber, branchNumber and DateFrom to.
Based on these variables I want to query the table (seen in picture below stored procedure) to return all records that meet the criteria I pass (through variables).
Instead I am getting this error:
Conversion failed when converting date and/or time from character string
It seems to be failing when I pass it the DateFrom variable.
Thank you for your help
ALTER PROCEDURE [dbo].[Search_Records]
#bankNumber varchar(3),
#branchNumber varchar(3),
#dateCreated datetime
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
#Bank_Number varchar(3) = #bankNumber,
#Branch_Number varchar(3) = #branchNumber,
#DateFrom datetime = #dateCreated,
#DateTo datetime = #dateCreated
SELECT DISTINCT
A.bankNumber,
A.branchNumber,
A.dateCreated
FROM
dbo.CENSORED A
WHERE
(#Branch_Number IS NULL OR bankNumber LIKE #BankNumber + '%')
AND (#Branch_Number IS NULL OR branchNumber LIKE #Branch_Number + '%')
AND (#DateFrom IS NULL OR dateCreated LIKE + #DateFrom + '%')
AND (#DateTo IS NULL OR dateCreated LIKE + #DateTo + '%')
END
You cannot use the LIKE operator with Datetime value. If you are matching only on month you would need to use MONTH() function. LIKE operator can only be used with string data types.
Dont see the point of all these Variables declared in your stored procedure, a simplified version should look something like ....
ALTER PROCEDURE [dbo].[Search_Records]
#bankNumber varchar(3),
#branchNumber varchar(3),
#dateCreated datetime
AS
BEGIN
SET NOCOUNT ON;
SELECT DISTINCT
A.bankNumber,
A.branchNumber,
A.dateCreated
FROM
dbo.CENSORED A
WHERE
(#Branch_Number IS NULL OR bankNumber LIKE #bankNumber + '%')
AND (#Branch_Number IS NULL OR branchNumber LIKE #branchNumber + '%')
AND (#dateCreated IS NULL OR (MONTH(dateCreated) = MONTH(#dateCreated)
AND
YEAR(dateCreated) = YEAR(#dateCreated)))
END
Note
this will produce a very inefficient execution plan, consider using dynamic sql for queries with optional parameters like this one.

Can a computed column in design reference another in sql server?

I have 2 computed columns, [StartTime] and [EndTime]
The [StartTime] and [EndTime] are calculated with a formula using the [Week] and [Year] columns.
Now I need another computed column, [Status] that is calculated using the first two. But it gives me an error in formula when I try to use one of them inside the formula of [Status]
I really need this to work as I have no alternative. But is this even possible?
Here you go Mr -1 :
(case when [IsVOR]=(1) then 'VOR'
when [MarkedAsCompleteOn] IS NULL AND [Year]<datepart(year,getdate()) then 'Overdue'
when [MarkedAsCompleteOn] IS NULL AND [Year]>datepart(year,getdate()) then 'Not Due'
when [MarkedAsCompleteOn] IS NULL AND [Year]=datepart(year,getdate()) AND [Week]<datepart(iso_week,getdate()) then 'Overdue'
when [MarkedAsCompleteOn] IS NULL AND [Year]=datepart(year,getdate()) AND [Week]=datepart(iso_week,getdate()) then 'Due'
when [MarkedAsCompleteOn] IS NULL AND [Year]=datepart(year,getdate()) AND [Week]>datepart(iso_week,getdate()) then 'Not Due'
when [MarkedAsCompleteOn] IS NOT NULL AND [Year]<datepart(year,[MarkedAsCompleteOn]) then 'Late'
when [MarkedAsCompleteOn] IS NOT NULL AND [Year]>datepart(year,[MarkedAsCompleteOn]) then 'Early'
when [MarkedAsCompleteOn] IS NOT NULL AND [Year]=datepart(year,[MarkedAsCompleteOn]) AND [Week]<datepart(iso_week,[MarkedAsCompleteOn]) then 'Late'
when [MarkedAsCompleteOn] IS NOT NULL AND [Year]=datepart(year,[MarkedAsCompleteOn]) AND [Week]=datepart(iso_week,[MarkedAsCompleteOn]) then 'On Time'
when [MarkedAsCompleteOn] IS NOT NULL AND [MarkedAsCompleteOn]<[AllocatedTimeStart] then 'Early' end)
The last part of it causes the error :
[MarkedAsCompleteOn]<[AllocatedTimeStart] then 'Early'
And the error is generic :
- Error validating the formula for column 'Status'.
No. One computed column can not be based on a different computed column. There's a specific error for this (1759):
Computed column '%s' in table '%s' is not allowed to be used in another computed-column definition.
You could create a view, based on the table, and perform a second round of computations within the view definition. Whether you then perform all activity against the view (adding triggers if required), or only use it for lookup is a design decision you'd need to make.
Of course, one you add the idea of using a view, you can build up multiple (not just 2) layers of computation by using a Common Table expression.
You do lose the ability to make the computed column persisted, unless the view is eligible for becoming an indexed view - not that this matters in this case, since it seems to be based on date calculations, so probably not persistable anyway.
I found my own solution in the end, by using a function, this kept my production app going without any changes.
USE [DBNAME]
GO
/****** Object: UserDefinedFunction [dbo].[GetStatus] Script Date: 01/02/2013 11:08:29 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[GetStatus](#CompletedOn DATETIME, #Year INT, #Week INT)
RETURNS NVARCHAR(MAX)
AS BEGIN
DECLARE #CurrentDate DATETIME
DECLARE #StartTime DATETIME
DECLARE #EndTime DATETIME
DECLARE #Status NVARCHAR(MAX)
SET #CurrentDate = GETDATE()
SET #StartTime = (dateadd(week,#Week-(1),dateadd(day,(-1),dateadd(week,datediff(week,(0),CONVERT([varchar](4),#Year,(0))+'-01-01'),(1)))))
SET #EndTime = (dateadd(week,#Week-(1),dateadd(day,(-1),dateadd(week,datediff(week,(0),CONVERT([varchar](4),#Year,(0))+'-01-01'),(8)))))
SET #Status = '-'
IF(#CompletedOn IS NULL)
BEGIN
IF(#CurrentDate < #StartTime)
SET #Status = 'Not Due'
IF(#CurrentDate > #StartTime AND #CurrentDate < #EndTime)
SET #Status = 'Due'
IF(#CurrentDate > #EndTime)
SET #Status = 'Overdue'
END
ELSE
BEGIN
IF(#CompletedOn < #StartTime)
SET #Status = 'Early'
IF(#CompletedOn > #EndTime)
SET #Status = 'Late'
ELSE
SET #Status = 'On Time'
END
RETURN #Status
END
And in the status field I put the formula :
([dbo].[GetStatus]([MarkedAsCompleteOn],[Year],[Week]))
This is my first ever function in sql server, so it may not be optimum.

How to compare multiple values in one column against a delimited string in a stored procedure

Ok, first question, and you guys scare me with how much you know, so please be gentle...
I am trying to pass in a delimited string and convert it to an array in a stored procedure and then use the array to check against values in a column. Here's the catch. I'm trying to take the preexisting table, that checks for one association and expand it to allow for multiple associations.
So the column annAssociations might have three ids, 4,16,32, but I need to check if it belongs to the groupIds being queried, 6,12,32. Since one of the values matched, it should return that row.
Here is the procedure as it exists.
CREATE PROCEDURE [dbo].[sp_annList]
-- Date Range of Announcements.
#dateBegin datetime,
#dateEnd datetime,
-- Announcement type and associations.
#annType varchar(50),
#annAssociation varchar(255)
AS
BEGIN
-- Set the SELECT statement for the announcements.
SET NOCOUNT ON;
-- See if this should be a limited query
IF #annAssociation <> ''
Begin
SELECT *
FROM announcements
WHERE (date1 <= #dateEnd AND date2 >= #dateBegin) -- See if the announcement falls in the date range.
AND annType = #annType -- See if the announcement is the right type.
AND annAssociations LIKE (select SplitText from dbo.fnSplit(#annAssociation, ','))
ORDER BY title
END
Else
Begin
SELECT *
FROM announcements
WHERE (date1 <= #dateEnd AND date2 >= #dateBegin)
AND annType = #annType
ORDER BY title
End
END
And here is the method I'm using to convert the delimited string and store it in a temporary table.
CREATE Function [dbo].[fnSplit](#text text, #delimitor nchar(1))
RETURNS
#table TABLE
(
[Index] int Identity(0,1),
[SplitText] varchar(10)
)
AS
BEGIN
declare #current varchar(10)
declare #endIndex int
declare #textlength int
declare #startIndex int
set #startIndex = 1
if(#text is not null)
begin
set #textLength = datalength(#text)
while(1=1)
begin
set #endIndex = charindex(#delimitor, #text, #startIndex)
if(#endIndex != 0)
begin
set #current = substring(#text,#startIndex, #endIndex - #StartIndex)
Insert Into #table ([SplitText]) values(#current)
set #startIndex = #endIndex + 1
end
else
begin
set #current = substring(#text, #startIndex, datalength(#text)-#startIndex+1)
Insert Into #table ([SplitText]) values(#current)
break
end
end
end
return
END
Sorry for the long question. I just wanted to get all the info out there. I've been researching for days, and I either don't know where to look or am missing something obvious.
You probably won't get much better performance than this approach (well you might see better performance with a CLR split function but at 3 or 4 items you won't see much difference):
SELECT *
FROM announcements AS a
WHERE ...
AND EXISTS (SELECT 1 FROM dbo.fnSplit(#annAssociation) AS n
WHERE ',' + a.annList + ',' LIKE '%,' + n.SplitText + ',%');
The key here is that you only need to split up one of the lists.
You really should stop storing multiple values in the annAssocations column. Each id is a separate piece of data and should be stored separately (in addition to better conforming to normalization, it will make queries like this simpler).

T-SQL - get date by dynamic params

I tried to figure out a dynamic query to get date col within past 20 days. The idea is quite simple and, moreover, I know the table does contain dates from getdate() to -20 days but still no result get returned
DECLARE #date_past_period varchar(MAX);
DECLARE #date_past_number varchar(MAX);
SET #date_past_period='day';
SET #date_past_number='20';
DECLARE #aDate datetime;
DECLARE #sql varchar(MAX);
SET #sql='SELECT date FROM table WHERE convert(varchar,date,121) BETWEEN convert(varchar,getdate(),121) AND convert(varchar,dateadd('+#date_past_period+', -'+#date_past_number+', getdate()),121)';
exec(#sql);
Maybe the problem is in dynamic thing but I am not sure.
Any useful comment is appreciated
You can use CASE function (T-SQL):
CREATE PROCEDURE MyStoredProcedure
#IntervalType VARCHAR(15),
#Num INT
AS
DECLARE #StartDate DATETIME = GETDATE();
DECLARE #EndDate DATETIME =
CASE #IntervalType
WHEN 'DAY' THEN DATEADD(DAY,#Num,#StartDate)
WHEN 'MONTH' THEN DATEADD(MONTH,#Num,#StartDate)
WHEN 'YEAR' THEN DATEADD(YEAR,#Num,#StartDate)
END;
IF #EndDate IS NULL
RAISERROR('Invalid params', 16, 1);
ELSE
SELECT date FROM table WHERE date BETWEEN #StartDate AND #EndDate;
By converting to VARCHAR your search condition from WHERE will not be SARG ( 1 & 2 ).
I am pretty sure this scenario can be covered without using dynamic SQL, however, one obvious problem in your SQL is the between clause - the range is in the wrong order. Try changing your #sql as below:
SET #sql='SELECT date FROM table WHERE convert(varchar,date,121) BETWEEN convert(varchar,dateadd('+#date_past_period+', -'+#date_past_number+', getdate()),121) AND convert(varchar,getdate(),121)';

Resources