How do I write a MS SQL statement for the below condition?
I have a form that allows users to enter dates (fromDate & toDate) and ID (fromID & toID) in range. The fields can be blank for all OR enter only either from or to field OR enter both from and to fields. Selection is based on the entered values to select. Below are the conditions checking in where clause for value entered.
no value entered => skip all conditions
value entered in fromDate only => Date = frDate
value entered in toDate only => Date <= toDate
value entered in both fromDate & toDate => Date between fromDate and toDate
Condition is applied to ID field as well.
Any advice is highly appreciated.
Thanks in advance.
You can solve your problem using dynamic query. Your question is not fully clear. Here i'm giving you a solution which will help you to solve your problem. Try this:
1. Create Dynamic query in a Store Procedure
CREATE PROCEDURE sp_YourSPName
/* Input Parameters */
#FromDate DATETIME ,
#ToDate DATETIME
AS
SET NOCOUNT ON
/* Variable Declaration */
DECLARE #SQLQuery AS NVARCHAR(4000)
DECLARE #ParamDefinition AS NVARCHAR(2000)
/* Build the Transact-SQL String with the input parameters */
SET #SQLQuery = 'Select * From YourTableName where (1=1) '
/* check for the condition and build the WHERE clause accordingly */
IF (#FromDate IS NOT NULL)
AND (#ToDate IS NOT NULL)
SET #SQLQuery = #SQLQuery +
' And (YourDate BETWEEN #FromDate AND #ToDate)'
IF (#FromDate IS NULL)
AND (#ToDate IS NOT NULL)
SET #SQLQuery = #SQLQuery + ' And (YourDate <= #ToDate)'
IF (#FromDate IS NOT NULL)
AND (#ToDate IS NULL)
SET #SQLQuery = #SQLQuery + ' And (YourDate = #FromDate)'
/* Specify Parameter Format for all input parameters included
in the stmt */
SET #ParamDefinition = '#StartDate DateTime,
#EndDate DateTime'
/* Execute the Transact-SQL String with all parameter value's Using sp_executesql Command */
EXECUTE sp_Executesql #SQLQuery,
#ParamDefinition,
#FromDate,
#ToDate
IF ##ERROR <> 0
GOTO ErrorHandler
SET NOCOUNT OFF
RETURN(0)
ErrorHandler :
RETURN(##ERROR)
GO
2. Execute Store Procedure:
EXEC sp_YourSPName '01 Oct 2018', '01 Oct 2018'
For more info see this link
You can use IS NULL to check param has value
SELECT * FROM Table
WHERE (#FromDate IS NULL OR Date > #FromDate) AND (#ToDate IS NULL OR Date < #ToDate)
Same type of query will be used for Id
Below is the EXAMPLE and not the exact query you can try to put it in your way using CASE statements
SELECT values
FROM Table
WHERE CASE
WHEN fromDate = null & todate = null THEN
WHEN fromDate != null & toDate != null THEN Date between fromDate and toDate
WHEN fromDate != null THEN Date = frDate
WHEN toDate != null THEN Date = toDate
Related
I have a stored procedure that takes on range of dates:
Create Procedure Search_PO
(
#usersID CHAR(10),
#poNo VARCHAR(20),
#poDateFrom Date,
#poDateTo Date,
)
As
Begin
If (#poNo = '')
Begin
Set #poNo = Null
End
If (#poDateFrom = '01/01/0001')
Begin
Set #poDateFrom = Null
End
If (#poDateTo = '01/01/0001')
Begin
Set #poDateTo = Null
End
Select * From PurchaseOrder p, Users u, Warehouse w
Where p.warehouseID = w.warehouseID
and w.usersID = u.usersID
and u.usersID = #usersID
and ((p.poNo like '%' + #poNo + '%') or #poNo Is Null)
and (p.poDate >= convert(date, #poDateFrom, 103) Or #poDateFrom Is Null)
and (p.poDate <= convert(date, #poDateTo, 103) Or #poDateTo Is Null)
End
This worked normally when I had selected dates where it was below 12(number of months), it throws me back an error of conversion from varchar into date
I believe this is due to the fact that:
Date format in SQL Server is mm/dd/yyyy
Date format in Visual Studio is dd/mm/yyyy
I tried using this code as a standalone code to check if my conversion is working:
select * from PurchaseOrder where poDate <= convert(date,'31/5/2017',103)
It does work, but when I execute my stored procedure:
exec Search_PO 'US00000001','','1/1/0001','31/5/2017'
It returns me the conversion error again. Thank you in advance for any kind of help.
I think the problem is in
exec Search_PO 'US00000001','','1/1/0001','31/5/2017'
You should pass date type parameter on yyyymmdd or yyyy-mm-dd format, not dd/mm/yyyy.
Change it to:
exec Search_PO 'US00000001','','1/01/01','2017/05/31'
And you don't need to convert convert(date, #poDateFrom, 103), its type is DATE already.
just
and (p.poDate >= #poDateFrom Or #poDateFrom Is Null)
and (p.poDate <= #poDateTo Or #poDateTo Is Null)
Can you send the dates as text variables and then make the conversion in the stored procedure? You can use SET DATEFORMAT dmy to aling SQL Server and Visual Studio date formats.
With this modification your SP would be like this:
Create Procedure Search_PO
(
#usersID CHAR(10),
#poNo VARCHAR(20),
#poDateFrom_Chr VARCHAR(10),
#poDateTo_Chr VARCHAR(10),
)
As
Begin
DECLARE #poDateFrom DATE
DECLARE #poDateTo DATE
SET DATEFORMAT dmy
SET #poDateFrom = #poDateFrom_Chr
SET #poDateTo = #poDateTo_Chr
SET DATEFORMAT mdy
If (#poNo = '')
Begin
Set #poNo = Null
End
If (#poDateFrom = '01/01/0001')
Begin
Set #poDateFrom = Null
End
If (#poDateTo = '01/01/0001')
Begin
Set #poDateTo = Null
End
Select * From PurchaseOrder p, Users u, Warehouse w
Where p.warehouseID = w.warehouseID
and w.usersID = u.usersID
and u.usersID = #usersID
and ((p.poNo like '%' + #poNo + '%') or #poNo Is Null)
and (p.poDate >= convert(date, #poDateFrom, 103) Or #poDateFrom Is Null)
and (p.poDate <= convert(date, #poDateTo, 103) Or #poDateTo Is Null)
End
Hope it helps.
You are currently converting your two date paramenters twice - once in the procdeure declaration (implicitly) and once in your select statement (explicitly). Your procedure is failing at the point where the #poDateFrom and #poDateTo parameters are being implicitly cast as date in the stored procedure declaration. If you're not in control of the format of the date being passed to your procedure you should change the parameter type to varchar.
i.e.
ALTER Procedure Search_PO
(
#usersID CHAR(10),
#poNo VARCHAR(20),
#poDateFrom VARCHAR(10),
#poDateTo VARCHAR(10),
)
This will avoid the implicit conversion and rely only on your explicit conversion (i.e. convert(date, #poDateFrom, 103) ) which, as you've already shown, will work for string value '31/5/2017'
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..
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.
I have a SQL stored procedure for a search page on a website where a user can search records by, and between, two date fields: initiatedDateStart and initiatedDateEnd. The logic for the SQL query should be as follows:
If the startDate has a value, but the endDate is empty, or equal to
the startDate, return records that were created ON the startDate.
If the startDate has a value, and the endDate value is greater than
the startDate, return records that were created BETWEEN the two
dates.
Since I'm not a SQL expert, my stored procedure is not very elegant or clever, but it does return the records I expect it to, except for the date fields. I have researched for this, but the syntax and logic is stumping me. Here is a snippet of my stored procedure. If a value is entered in the initStartDate texbox, but the initEndDate is empty, this returns ALL the records created AFTER the start date. I appreciate any and all help on this.
DECLARE #initStartDate datetime = NULL
DECLARE #initEndDate datetime = NULL
SELECT DISTINCT
d.[DCRId],
d.[Title],
d.[FiscalYear]
FROM [dbo].[tblDCR] d
LEFT OUTER JOIN [dbo].[tblWorkflow] orig ON (d.[DCRId] = orig.[DCRId] AND orig.StepName = 'Draft')
WHERE 1 = 1
AND (orig.BadgeDate >= #initStartDate OR #initStartDate IS NULL)
AND (orig.BadgeDate <= #initEndDate OR #initEndDate IS NULL)
The best way I can think of to handle this would be to use dynamic sql
DECLARE #initStartDate datetime = NULL;
DECLARE #initEndDate datetime = NULL;
Declare #Sql NVARCHAR(MAX);
SET #Sql = N'SELECT DISTINCT
d.[DCRId],
d.[Title],
d.[FiscalYear]
FROM [dbo].[tblDCR] d
LEFT OUTER JOIN [dbo].[tblWorkflow] orig
ON (d.[DCRId] = orig.[DCRId] AND orig.StepName = ''Draft'')
WHERE 1 = 1 '
+ CASE WHEN #initStartDate IS NOT NULL THEN
N' AND orig.BadgeDate >= #initStartDate ' ELSE N'' END
+ CASE WHEN #initEndDate IS NOT NULL THEN
N' AND orig.BadgeDate <= #initEndDate ' ELSE N'' END
Exec sp_executesql #Sql
,N'#initStartDate datetime, #initEndDate datetime'
,#initStartDate
,#initEndDate
I think a solution to your problem would be to assign the current date to the end parameter when it is left NULL. By doing this, a user can enter no parameters and get the current date values, enter just the start date and get data on the start date, or enter the end date and get data between the current date and the end date. As a final catch, you can tell the procedure to return only today's data if for some reason a user puts a higher start date than end date.
CREATE PROCEDURE test_proc
#initStartDate date = null,
#initEndDate date = null
AS
IF #initStartDate IS NULL AND #initEndDate IS NULL
BEGIN
SET #initStartDate = (SELECT GETDATE())
SET #initEndDate = #initStartDate
END
ELSE IF #initStartDate IS NULL AND #initEndDate IS NOT NULL
BEGIN
SET #initStartDate = #initEndDate
END
ELSE IF #initEndDate IS NULL AND #initStartDate IS NOT NULL
BEGIN
SET #initEndDate = #initStartDate
END
IF #initStartDate > #initEndDate
BEGIN
SET #initStartDate = (SELECT GETDATE())
SET #initEndDate = #initStartDate
END
SELECT DISTINCT
d.[DCRId],
d.[Title],
d.[FiscalYear]
FROM [dbo].[tblDCR] d
LEFT OUTER JOIN [dbo].[tblWorkflow] orig ON (d.[DCRId] = orig.[DCRId] AND orig.StepName = 'Draft')
WHERE orig.BadgeDate BETWEEN #initStartDate AND #initEndDate
GO
My modified SQL
DECLARE #initStartDate date = '10/21/15'
DECLARE #initEndDate date = NULL
IF #initStartDate IS NULL AND #initEndDate IS NOT NULL
BEGIN
SET #initStartDate = #initEndDate
END
ELSE IF #initEndDate IS NULL AND #initStartDate IS NOT NULL
BEGIN
SET #initEndDate = #initStartDate
END
SELECT DISTINCT
d.[DCRId],
d.[Title],
d.[FiscalYear]
FROM [dbo].[tblDCR] d
LEFT OUTER JOIN [dbo].[tblWorkflow] orig ON (d.[DCRId] = orig.[DCRId] AND orig.StepName = 'Draft')
WHERE 1 = 1
AND (orig.BadgeDate BETWEEN #initStartDate AND #initEndDate) OR (#initStartDate IS NULL OR #initEndDate IS NULL)
but what if the #initStartDate does not have a value ?
assuming you want it to go all the way back if no startDate criteria, then, pass the date criteria as Nullable parameters, as you are:
then, (assuming the database field is date only with no time), use the following where clause:
where orig.BadgeDate Between
Coalesce(#initStartDate, orig.BadgeDate) and
Coalesce(#initEndDate, #initStartDate, orig.BadgeDate)
I’m executing a procedure like this:
EXEC myProcedure #name = 'Smith', #dateDeleted = NULL
I need all the Smith that don’t have a deleted date.
And this is the procedure:
CREATE PROCEDURE [dbo].[myProcedure]
#name VARCHAR(8000) = NULL
,#dateDeleted VARCHAR(8000) = NULL
AS
BEGIN
SET NOCOUNT ON;
WITH t
(name
,dateDeleted
)
AS
(
SELECT DISTINCT
name,dateDeleted FROM mytable
WHERE
(#name IS NULL OR #name = name)
AND (#dateDeleted IS NULL OR CONVERT(DATETIME, #dateDeleted, 102) = dateDeleted)
)
After the execution I have all the Smith but it does not pay any attention to the dateDeleted = NULL .. I ge all the Smiths no matter if they have a deleted date
How can I fix this?
Thanks
In your request if you pass NULL then a condition always true.Try this WHERE clause with COALESCE expression:
WHERE (#name IS NULL OR #name = name)
AND (COALESCE(#dateDeleted, dateDeleted) IS NULL
OR CONVERT(DATETIME, #dateDeleted, 102) = dateDeleted)
You need to set ansi nulls on
Execute:
set ansi_nulls on
And then execute the query.
Here is the explantion for this behaviour
http://msdn.microsoft.com/en-us/library/ms188048.aspx