Stored procedure with nullable value in date field - c#

In this stored procedure , in a where condition if #startDate and #EndDate values are null then how it can be handle using COALESCE.
CREATE PROCEDURE dbo.SP_ManageLeaveSearch
#StartDate datetime,
#EndDate datetime,
#UserName CHAR(100),
#MarketID INT
AS
BEGIN
SELECT d1.UserName,c1.HouseName,c.StartDate,c.EndDate
FROM table1 c
Inner JOIN table2 d1 ON c.UserID = d1.UserID
WHERE
(
(
(#StartDate BETWEEN StartDate AND EndDate)
OR
(#EndDate BETWEEN StartDate AND EndDate)
OR
(
(#StartDate <= Startdate AND #EndDate>=EndDate)
)
)
AND
(
d1.UserName = COALESCE(#UserName, d1.UserName)
)
)
END
Thnaks in advance.

This should work for you:
CREATE PROCEDURE dbo.ManageLeaveSearch
#StartDate datetime = NULL,
#EndDate datetime = NULL,
#UserName CHAR(100) = NULL,
#MarketID INT
AS
BEGIN
SELECT d1.UserName,c1.HouseName,c.StartDate,c.EndDate
FROM table1 c
Inner JOIN table2 d1 ON c.UserID = d1.UserID
WHERE
COALESCE(#StartDate,StartDate) <= EndDate AND
StartDate <= COALESCE(#EndDate,EndDate) AND
d1.UserName = COALESCE(#UserName, d1.UserName)
END
Notes:
Don't name stored procedures with an sp_ prefix - it's reserved for Microsoft's system procedures.
I've gone with simpler conditions for determining an overlap exists. An overlap exists between two ranges if range 1 starts before range 2 ends, and range 2 starts before range 1 ends.
I've specified defaults for those parameters that should be nullable.

Try this one -
CREATE PROCEDURE dbo.usp_ManageLeaveSearch
#StartDate DATETIME,
#EndDate DATETIME,
#UserName CHAR(100),
#MarketID INT
AS BEGIN
SELECT
d1.UserName
, c.HouseName
, c.StartDate
, c.EndDate
FROM dbo.table1 c
JOIN dbo.table2 d1 ON c.UserID = d1.UserID
WHERE d1.UserName = ISNULL(#UserName, d1.UserName)
AND (
ISNULL(#StartDate, StartDate) BETWEEN StartDate AND EndDate
OR
ISNULL(#EndDate, EndDate) BETWEEN StartDate AND EndDate
)
END

You've overly complicated things. This should work for you, and is as simple of a query as I know of. I prefer this syntax because in most of my use cases, the ...OR #UserName IS NULL can be removed from the query before it is even executed thereby making a very simple, fast execution.
CREATE PROCEDURE dbo.SP_ManageLeaveSearch
#StartDate datetime,
#EndDate datetime,
#UserName CHAR(100),
#MarketID INT
AS
BEGIN
SELECT d1.UserName,c1.HouseName,c.StartDate,c.EndDate
FROM table1 c
JOIN table2 d1
ON c.UserID = d1.UserID
WHERE (#StartDate<=EndDate OR #StartDate IS NULL)
AND (#EndDate>=StartDate OR #EndDate IS NULL)
AND (d1.UserName = #UserName OR #UserName IS NULL)
END

Related

Convert this inline SQL to stored procedure

How can I convert this inline SQL to a stored procedure
SELECT
PM.ProjectName
,[PurposeorReason]
,Reg.Name
,EA.Comment as Comment
,[FromDate]
,[VoucherID]
,[TotalAmount]
,ex.CreatedOn
FROM [TimesheetDB].[dbo].[Expense] ex
inner join Registration Reg on reg.RegistrationID = ex.UserID
inner join ProjectMaster PM on ex.ProjectID =PM.ProjectID
inner join AssignedRoles AR on reg.RegistrationID = AR.RegistrationID
inner join ExpenseAuditTB EA on ex.ExpenseID = EA.ExpenseID
where FromDate between '2019-09-25' and '2019-09-29'
and ea.ProjectID IN (1,2,5)
and EA.Status = 2
I have issues with the (1,2,5) part. I have it in C# as a string "1,2,5" and the ProjectID is integer.
I know I am doing something wrong. The query itself works well.
I suggest a table-valued parameter to pass lists/arrays to a stored procedure. In the C# code, specify parameter type SqlDbType.Structured as the parameter type. The parameter value can be a DataTable, IEnumerable<SqlDataRecord>, or DbDataReader. I suggest a DataTable with a single column for this use case.
CREATE TYPE dbo.TVPProjectIdList AS TABLE (
ProjectId int NOT NULL PRIMARY KEY
);
GO
CREATE PROCEDURE dbo.Example
#StartDate date
, #EndDate date
, #Status int
, #ProjectIdList dbo.TVPProjectIdList READONLY
AS
SET NOCOUNT ON;
SELECT
PM.ProjectName
,[PurposeorReason]
,Reg.Name
,EA.Comment as Comment
,[FromDate]
,[VoucherID]
,[TotalAmount]
,ex.CreatedOn
FROM [TimesheetDB].[dbo].[Expense] ex
inner join Registration Reg on reg.RegistrationID = ex.UserID
inner join ProjectMaster PM on ex.ProjectID =PM.ProjectID
inner join AssignedRoles AR on reg.RegistrationID = AR.RegistrationID
inner join ExpenseAuditTB EA on ex.ExpenseID = EA.ExpenseID
where FromDate between #StartDate and #EndDate
and ea.ProjectID IN (SELECT ProjectId FROM #ProjectIdList)
and EA.Status = #Status;
GO
You have to add commas at the beginning and at the end of #ProjectId string.
In c# How to Get comma value at the beginning and at the end
string str = "1,2,5";
string replaced=str.Replace(',',',');
string concatenatdvalue=","+replaced+',';
Result = ",1,2,5,"
Then result value you can Pass as #ProjectId into SQL Server......
CREATE PROCEDURE dbo.sp_ProjectReport
(
#FromDate VARCHAR(20)=NULL,
#ToDate VARCHAR(20)=NULL,
#ProjectId VARCHAR(50)=NULL,
#StatusId INT=NULL
)
AS
BEGIN
SELECT
PM.ProjectName
,[PurposeorReason]
,Reg.Name
,EA.Comment as Comment
,[FromDate]
,[VoucherID]
,[TotalAmount]
,ex.CreatedOn
FROM [TimesheetDB].[dbo].[Expense] ex
inner join Registration Reg on reg.RegistrationID = ex.UserID
inner join ProjectMaster PM on ex.ProjectID =PM.ProjectID
inner join AssignedRoles AR on reg.RegistrationID = AR.RegistrationID
inner join ExpenseAuditTB EA on ex.ExpenseID = EA.ExpenseID
where
convert(DATETIME,FromDate) BETWEEN Convert(DATETIME,CASE WHEN isnull(#FromDate,'')='' THEN FromDate ELSE isnull(#FromDate,'') END)
AND Convert(DATETIME, CASE WHEN isnull(#ToDate,'')='' THEN FromDate ELSE isnull(#ToDate,'') END)
and CHARINDEX(','+cast(ea.ProjectID as varchar(100))+',', #ProjectId) > 0
and EA.Status = #StatusId
END
Testing Script For Executing SP
EXEC dbo.sp_ProjectReport
#FromDate='2019-09-25',
#ToDate='2019-09-29',
#ProjectId=',1,2,5,',
#StatusId='2'
Note:- Here i'm changing also logic of FromDate to ToDate
.........null part is also Handle in Custom Date Range.......
For E.g.
If you are enter only FromDate as "07/06/2017" then it will give you
from result("07/06/2017" to last Date)

Passing formatted string and actual parameters to stored procedure from C#

I execute a stored procedure as follows:
exec SALESREPORTFORWEB
#StartDate = '03/20/2017', #EndDate = '03/21/2017'
Stored Procedure
CREATE proc [dbo].[SALESREPORTFORWEB]
--SALESREPORTFORWEB #StartDate='03-20-2017' ,#EndDate='03-28-2017',#usercode in ('2739','1609')
#StartDate DATETIME =NULL ,
#EndDate DATETIME =NULL ,
#ITEMCODE VARCHAR(100)=NULL,
#ITEMDESCRIPTION VARCHAR(100)=NULL,
#CLIENTCODE Varchar(25) = null,
#CLIENTNAME VARCHAR(100)=NULL,
#CLIENTBRANCHCODE VARCHAR(100)=NULL,
#CLIENTBRANCHNAME VARCHAR(100)=NULL,
#BRANDCODE VARCHAR (25)=NULL,
#BRANDNAME VARCHAR(100)=NULL,
#USERCODE VARCHAR(25)=NULL,
#USERNAME VARCHAR(100)=NULL,
#SUBCHANNEL VARCHAR(25)=NULL
AS
SELECT H.UserCode,U.SALESMANNAME, CONVERT(CHAR(10), H.TrxDate, 103) AS DATE,D.ItemCode,I.Description AS ITEMDESCRIPTION,d.ItemGroupLevel5 AS BRANDCODE,
B.Description AS BRANDNAME,
H.ClientCode,
C1.Description AS Client,H.ClientBranchCode,C2.Description, C2.SubChannelCode AS BRANCHSUBCHANNEL,
ROUND(
SUM(
CASE WHEN D.QuantityLevel1 > 0 THEN
D.QuantityLevel1 * PriceUsedLevel1
ELSE
D.QuantityLevel3 * PriceUsedLevel3
END - ISNULL(D.TotalDiscountAmount, 0)
), 2) AS TrxAmount,SUM(D.QuantityBU) AS QTY
FROM tblTrxHeader H INNER JOIN
tblTrxDetail D ON H.TrxCode = D.TrxCode AND D.TrxStatus > 0 INNER JOIN
tblBrand B ON B.Code=D.ITEMGROUPLEVEL5 INNER JOIN
tblClient C1 ON H.ClientCode = C1.Code
INNER JOIN tblClient C2 ON H.ClientBranchCode=C2.Code
INNER JOIN TBLITEM I ON I.ITEMCODE=D.ITEMCODE
/*LEFT OUTER JOIN
tblRegion R ON R.Code = C.RegionCode*/ LEFT OUTER JOIN
vw_UnitManagers U ON U.SalesmanCode = H.UserCode
WHERE
H.TrxType IN (1) AND
DATEDIFF(dd,H.TrxDate,ISNULL(#StartDate,GETDATE())) <= 0 AND DATEDIFF(dd,H.TrxDate,ISNULL(#EndDate,GETDATE())) >= 0 AND
D.ITEMCODE= ISNULL(#ITEMCODE,D.ITEMCODE) AND
H.CLIENTCODE= ISNULL(#CLIENTCODE,H.CLIENTCODE)AND
H.ClientBranchCode=ISNULL(#CLIENTBRANCHCODE,H.ClientBranchCode) AND
D.ItemGroupLevel5=ISNULL(#BRANDCODE,D.ItemGroupLevel5)AND
H.UserCode in (ISNULL(#USERCODE,H.UserCode)) AND
C2.SubChannelCode=ISNULL(#SUBCHANNEL,C2.SubChannelCode)AND
B.Description LIKE('%'+ISNULL(#BRANDNAME,B.Description)+'%')AND
I.Description LIKE('%'+ISNULL(#ITEMDESCRIPTION,I.Description)+'%')AND
C1.Description LIKE('%'+ISNULL(#CLIENTNAME,C1.Description)+'%')AND
C2.Description LIKE('%'+ISNULL(#CLIENTBRANCHNAME,C2.Description)+'%')AND
U.SalesmanName LIKE('%'+ISNULL(#USERNAME,U.SalesmanName)+'%')
GROUP BY
--CONVERT(VARCHAR, H.TrxDate, 101),
H.UserCode,U.SALESMANNAME,H.TRXDATE,D.itemcode,I.Description,d.ItemGroupLevel5,
B.Description, H.ClientCode,C1.Description,H.ClientBranchCode,C2.Description, C2.SubChannelCode
ORDER BY H.TrxDate
where #StartDate = '03/20/2017' and #EndDate = '03/21/2017' are the parameters of the stored procedure.
In my code this is how it looks:
var salesDataQuery = SalesDataModel.FromSql("exec SALESREPORTFORWEB '#StartDate='#StartDate, '#EndData='#EndData",
new SqlParameter("#StartDate", startdate),
new SqlParameter("#EndData", enddate));
But this code throws an error:
Invalid syntax error near '#StartDate='
Can somebody help me make the right stored procedure call?
Many thanks!
How about cropping parameters form exec like that:
var salesDataQuery = SalesDataModel.FromSql("exec SALESREPORTFORWEB #StartDate, #EndDate",
new SqlParameter("#StartDate", startdate),
new SqlParameter("#EndData", enddate));
Edit: added parameters to procedure.

Entity Framework stored procedure return type changed

I mostly update my data model by deleting my .EDMX file and adding it again, just to make sure I get everything I have in the database.
I ran into a strange issue, where one of my stored procedure return types has been changed after deleting and re-adding the .EDMX. The stored procedure code remains unchanged, and can be found below. I am not sure what wrong I did?
SQL Server stored procedure (never changed):
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER procedure [dbo].[usp_SearchOrders]
#orderid int = null, #statusid int = null,
#startdate datetime = null, #enddate datetime = null,
#customername varchar(30) = null, #customeraddress varchar(30) = null
AS
SELECT
O.OrderID Order_ID, O.OrderDate,
OrderTotal = (SELECT SUM(od.UnitPrice - (od.UnitPrice * od.Discount))
FROM [Order Details] od
WHERE od.OrderID = O.OrderID),
Discount = (SELECT SUM(od.UnitPrice * od.Discount)
FROM [Order Details] od
WHERE od.OrderID = O.OrderID),
CC.Email1, CC.Phone,
Status = (SELECT OS.OrderStatusName
FROM OrderStatus OS
WHERE OS.OrderStatusID = O.OrderStatusID),
OrderType = (SELECT OT.OrderTypeName
FROM OrderType OT
WHERE OT.OrderTypeID = O.OrderTypeID)
FROM
Orders O
JOIN
Customers C ON O.CustomerID = C.CustomerID
JOIN
CustomersContactDetails CC ON C.CustomerID = CC.CustomerID
WHERE
(O.OrderID = #orderid OR #orderid IS NULL)
AND (O.OrderStatusID = #statusid OR #statusid IS NULL)
AND (O.OrderDate >= #startdate OR #startdate IS NULL)
AND (O.OrderDate <= #enddate OR #enddate IS NULL)
AND (C.CustomerName LIKE #customername OR #customername IS NULL)
AND (CC.Address LIKE #customeraddress OR #customeraddress IS NULL)
AND (CC.City LIKE #customeraddress OR #customeraddress IS NULL)
C# code: _dbContext.usp_SearchOrders(1,1,DateTime.Now, DateTime.Now.AddDays(1),'Hitin','BH');
Before update return type: usp_SearchOrders_Result
After re-adding return type: int
I never made any complex type or did any mapping, the class usp_SearchOrders_Result was created on it own.
What could be the possible reason behind this issue?
You need to have "SET NOCOUNT ON" at the top of your stored procedure.

Sql server get result of one month before

I have the following query
DECLARE #StartDate DATETIME, #EndDate DATETIME
SET #StartDate = DATEADD(mm,-1, getdate())
select count(status) from [full]
where (date_reception> #StartDate and status = 'OPEN')
I need to get result of one month before now , for example we are in 2015-03-19 i need to get result from 2015-02-19 till now.
When i try query above i get as result (4412) and when i try (where date_reception >'2015-02-19') i get (5638)
If the time component of the date is not to be considered, try the following code. If it is, your current code seems accurate.
DECLARE #StartDate DATETIME, #EndDate DATETIME, #currentDate date
set #currentDate = GETDATE()
SET #StartDate = DATEADD(mm,-1, #currentDate))
select count(status) from [full]
where (date_reception> #StartDate and status = 'OPEN')
try
WHERE date_reception BETWEEN DATEADD(month, -1, GETDATE()) AND DATEADD(GETDATE())

dates being ignored when type is passed

Any idea when i pass the type to the stored proecedure the dates are being ignored
ALTER PROCEDURE [dbo].[hms_GetBenefitsByDateType]
(
#id int,
#startDate datetime,
#EndDate datetime,
#bType int
)
AS
SET NOCOUNT ON;
SELECT benefit.emp_no, benefit.record_id, benefit.contract_id, benefit.career_id, benefit.date_from, benefit.date_to, benefit.benefit_type, benefit.monthly_value, benefit.benefit_provider, benefit.level_of_cover, benefit.current_benefit, benefit.previous_monthly_cost, benefit.benefit_change_details, benefit.notes, benefit.level_description, benefit.monthly_annual, benefit.cover_level, benefit.qualifying_reason, benefit_type.desc_
FROM benefit INNER JOIN
benefit_type ON benefit.benefit_type = benefit_type.code
WHERE (benefit.benefit_type = #bType) or (benefit.emp_no = #id) and (benefit.date_from >= #startDate) and (benefit.date_to <= #EndDate)
where date from is 2006-01-01 00:00:00.000 and date to is 1900-01-01 00:00:00.000
The result being produced is the following
11,4,21,123,2006-01-01 00:00:00.000,1900-01-01 00:00:00.000,3,15.00,1,2.00,1,0.00,None ,Notes ,Children ,1,1,1,Medical Cover - Children
12,6,14,27,2013-06-21 00:00:00.000,2013-06-21 00:00:00.000,3,500.00,0,0.00,1,0.00,
i would go for where like this one
WHERE (benefit.benefit_type = #bType) or (benefit.emp_no = #id) and ( (benefit.date_from >= #startDate) and (benefit.date_to <= (#EndDate + 1)) )
#UPDATE 1
WHERE (benefit.benefit_type = #bType) or (benefit.emp_no = #id) and ( (benefit.date_from IS NULL or benefit.date_from >= #startDate) and ( benefit.date_to IS NULL or benefit.date_to <= (#EndDate + 1)) )
I also think your problem lies in the where condition. I think you should add more parenthesis to make the condition more clear. For ex you can try the following (Hoping I got it right)
WHERE ((benefit.benefit_type = #bType) OR (benefit.emp_no = #id)) and
((benefit.date_from >= #startDate) and (benefit.benefit_type <= #EndDate))

Categories

Resources