Optionnal parameter in SEARCH CFQL method not of type varchar - codefluent

Is it possible to have a search function that would allow passing optional parameters other than varchar (i.e. DateTime, decimal .. ) ?
I need to search rows that are in a date range. User should be able to search FROM a date only, or up TO a date, or even in a FROM-TO range.
My approach was to create a SEARCH method with Date parameters. Those are correctly converted to DateTime object in CFE, but I won't be able to pass null value.
I managed to create a SEARCH method with unchecked parts, but those parts won't get optionnal in the body of the function.
How can I get fromDate and toDate parameters to be set as optional ?
CFQL body is
SEARCH(string amount, string fromDate, string toDate, string otherEntityId, date date) WHERE [$Entity::Date$ >= CAST(#fromDate AS DATE)] AND [$Entity::Date$ <= CAST(#toDate AS DATE)] AND OtherEntity.OtherEntityId = #otherEntityId AND Amount = #amount and date = #date
Body procedure generated is as follow. Notice the unchecked parts that aren't optionals
CREATE PROCEDURE [Schema].[Entity_NameOfProcedure]
(
#amount [nvarchar] (256) = NULL,
#fromDate [nvarchar] (256) = NULL,
#toDate [nvarchar] (256) = NULL,
#OtherEntityId [nvarchar] (256) = NULL,
#date [date] = NULL,
#_orderBy0 [nvarchar] (64) = NULL,
#_orderByDirection0 [bit] = 0
)
AS
SET NOCOUNT ON
DECLARE #sql nvarchar(max), #paramlist nvarchar(max)
SELECT #sql=
'SELECT DISTINCT * /*on purpose for stackoverflow */
FROM [Schema].[Entity]
LEFT OUTER JOIN [Schema].[OtherEntity] ON ([Schema].[Entity].[Entity_OtherEntity_OtherEntityId] = [Schema].[OtherEntity].[OtherEntity_OtherEntityId])
WHERE (([Entity].[Entity_Date] >= CAST(#fromDate AS DATE) AND ([Entity].[Entity_Date] <= CAST(#toDate AS DATE) AND ((1 = 1) AND ((1 = 1) AND (([Schema].[OtherEntity].[OtherEntity_NumberInt] LIKE ''6%'') AND (1 = 1)))))) AND (1 = 1))'
SELECT #paramlist = '#amount nvarchar (256),
#fromDate nvarchar (256),
#toDate nvarchar (256),
#otherEntityId nvarchar (256),
#date date,
#_orderBy0 nvarchar (64),
#_orderByDirection0 bit'
IF #amount IS NOT NULL
SELECT #sql = #sql + ' AND (([Schema].[Entity].[Entity_amount] = #amount))'
IF #otherEntityId IS NOT NULL
SELECT #sql = #sql + ' AND (([Schema].[OtherEntity].[OtherEntity_OtherEntityId] = #OtherEntityId))'
IF #date IS NOT NULL
SELECT #sql = #sql + ' AND (([Schema].[Entity].[Entity_Date] = #date))'
EXEC sp_executesql #sql, #paramlist,
#amount,
#fromDate,
#toDate,
#OtherEntityId,
#date,
#_orderBy0,
#_orderByDirection0
RETURN
GO
Thanks for your answer

You can create a SEARCH method with optional date parameters:
SEARCH(date fromDate, date toDate)
WHERE CreationDate >= #fromDate AND CreationDate <= #toDate
This generate the following SQL:
SELECT #sql=
'SELECT DISTINCT [Employee_Id], [Employee_FirstName], [Employee_CreationDate]
FROM [Employee]
WHERE (1 = 1)'
SELECT #paramlist = '#fromDate datetime, #toDate datetime'
IF #fromDate IS NOT NULL
SELECT #sql = #sql + ' AND (([Employee_CreationDate] >= #fromDate))'
IF #toDate IS NOT NULL
SELECT #sql = #sql + ' AND (([Employee_CreationDate] <= #toDate))'
The fromDate and toDate parameters are not nullable in the generated BOM. However if you use the default value which by default is equal to CodeFluentPersistence.DefaultDateTimeValue (More about default values), NULL will be sent to the store procedure.
If you prefer DateTime? just change the type of the parameter from date to date?
SEARCH(date? fromDate, date? toDate)
WHERE CreationDate >= #fromDate AND CreationDate <= #toDate
Which generate the following C# method:
public static EmployeeCollection Search(DateTime? fromDate, DateTime? toDate)

Related

Calculating the business differences in sql in the form of day, hours and minutes - SQL Server

With the below function I getting the result as 00:09:10 however I want the result to be as 01:00:10.
So hours is considered as considered as 1 day.
Example if hours is 30 then it will be 03:03:00 and so on
fn_GetHolidayMinutes : Get holiday in minutes between two dates and country
CREATE FUNCTION [dbo].[fn_GetHolidayMinutes]
(#StartDate DATETIME,
#EndDate DATETIME,
#CountryId BIGINT)
RETURNS BIGINT
AS
BEGIN
DECLARE #OUTPUT BIGINT;
DECLARE #HolidayList TABLE (HolidaysDate DATE)
-- Create Table #HolidayList
-- (
-- HolidaysDate date
-- )
DECLARE #Date1 DATE, #Date2 DATE
DECLARE holiday_cursor CURSOR FOR
SELECT StartDate,EndDate
FROM Holidays
WHERE IsActive = 1
AND CountryId = #CountryId
AND ((StartDate BETWEEN #StartDate AND #EndDate) OR
(EndDate BETWEEN #StartDate AND #EndDate))
OPEN HOLIDAY_CURSOR
FETCH NEXT FROM HOLIDAY_CURSOR INTO #Date1, #Date2
WHILE ##FETCH_STATUS = 0
BEGIN
--INSERT INTO #HolidayList
INSERT INTO #HolidayList
SELECT DATEADD(DAY, number, #Date1) [Date]
FROM master..spt_values
WHERE type = 'P'
AND DATEADD(DAY, number, #Date1) <= #Date2
FETCH NEXT FROM HOLIDAY_CURSOR INTO #Date1, #Date2
END
CLOSE HOLIDAY_CURSOR;
DEALLOCATE HOLIDAY_CURSOR;
(SELECT #OUTPUT= COUNT(DISTINCT HolidaysDate)
FROM #HolidayList
WHERE HolidaysDate BETWEEN #StartDate AND #EndDate
AND DATEPART(dw, HolidaysDate) NOT IN (SELECT DISTINCT number
FROM master..spt_values
WHERE number BETWEEN 1 and 7
AND number NOT IN (SELECT WorkingDay
FROM WorkingDays
WHERE CountryId = #CountryId AND IsActive = 1)
))
---print #OUTPUT; --this will give in days
--get the output in minutes
RETURN #OUTPUT * (SELECT TOP 1 STUFF(WorkingHours, 2, 2, '')
FROM dbo.WorkingDays
WHERE CountryId = #CountryId) * 60;
END
fn_GetWorkingDayMinuts :
CREATE FUNCTION [dbo].[fn_GetWorkingDayMinuts]
(#StartDate DATETIME,
#EndDate DATETIME,
#CountryId BIGINT)
--RETURNS BIGINT
RETURNS VARCHAR(250)
AS
BEGIN
DECLARE #Temp BIGINT
SET #Temp = 0
DECLARE #FirstDay DATE
SET #FirstDay = CONVERT(DATE, #StartDate, 112)
DECLARE #LastDay DATE
SET #LastDay = CONVERT(DATE, #EndDate, 112)
DECLARE #StartTime TIME
SET #StartTime = CONVERT(TIME, #StartDate)
DECLARE #FinishTime TIME
SET #FinishTime = CONVERT(TIME, #EndDate)
DECLARE #WorkStart TIME
SET #WorkStart = (SELECT CONVERT(VARCHAR(5),CONVERT(TIME, CONVERT(VARCHAR,CONVERT(DATE, GETDATE()))+ ' ' + (SELECT TOP 1
WorkStartTime FROM WorkingDays WHERE CountryId=#CountryId), 120)))
DECLARE #WorkFinish TIME
SET #WorkFinish = (SELECT CONVERT(VARCHAR(5),CONVERT(TIME, CONVERT(VARCHAR,CONVERT(DATE, GETDATE()))+ ' ' + (SELECT TOP 1
WorkEndTime FROM WorkingDays WHERE CountryId=#CountryId), 120)))
DECLARE #DailyWorkTime BIGINT
SET #DailyWorkTime = DATEDIFF(MINUTE, #WorkStart, #WorkFinish)
IF (#StartTime<#WorkStart)
BEGIN
SET #StartTime = #WorkStart
END
IF (#FinishTime>#WorkFinish)
BEGIN
SET #FinishTime=#WorkFinish
END
IF (#FinishTime<#WorkStart)
BEGIN
SET #FinishTime=#WorkStart
END
IF (#StartTime>#WorkFinish)
BEGIN
SET #StartTime = #WorkFinish
END
DECLARE #CurrentDate DATE
SET #CurrentDate = #FirstDay
DECLARE #LastDate DATE
SET #LastDate = #LastDay
WHILE(#CurrentDate<=#LastDate)
BEGIN
--IF (DATEPART(dw, #CurrentDate)!=1 AND DATEPART(dw, #CurrentDate)!=7)
IF(DATEPART(dw, #CurrentDate) IN (SELECT distinct number FROM master..spt_values WHERE number BETWEEN 1 and 7
AND number NOT IN (SELECT
WorkingDay FROM WorkingDays where CountryId=#CountryId and IsActive=1)
))
BEGIN
IF (#CurrentDate!=#FirstDay) AND (#CurrentDate!=#LastDay)
BEGIN
SET #Temp = #Temp + #DailyWorkTime
END
--IF it starts at startdate and it finishes not this date find diff between work finish and start as minutes
ELSE IF (#CurrentDate=#FirstDay) AND (#CurrentDate!=#LastDay)
BEGIN
SET #Temp = #Temp + DATEDIFF(MINUTE, #StartTime, #WorkFinish)
END
ELSE IF (#CurrentDate!=#FirstDay) AND (#CurrentDate=#LastDay)
BEGIN
SET #Temp = #Temp + DATEDIFF(MINUTE, #WorkStart, #FinishTime)
END
--IF it starts and finishes in the same date
ELSE IF (#CurrentDate=#FirstDay) AND (#CurrentDate=#LastDay)
BEGIN
SET #Temp = DATEDIFF(MINUTE, #StartTime, #FinishTime)
END
END
SET #CurrentDate = DATEADD(day, 1, #CurrentDate)
END
-- Return the result of the function
IF #Temp<0
BEGIN
SET #Temp=0
END
--RETURN #Temp -(dbo.fn_GetHolidayMinutes (DATEADD(dd, 0, DATEDIFF(dd, 0, #StartDate)),DATEADD(dd, 0, DATEDIFF(dd, 0,
#EndDate)),#CountryId))
--RETURN #Temp
DECLARE #theMinutes INT
DECLARE #Result VARCHAR(250)
SET #theMinutes = #Temp -(dbo.fn_GetHolidayMinutes (DATEADD(dd, 0,
DATEDIFF(dd, 0, #StartDate)),DATEADD(dd, 0, DATEDIFF(dd, 0,
#EndDate)),#CountryId))
--SET #Result= concat((#theMinutes / 540),':' , (#theMinutes % 540) /
60, ':', (#theMinutes % 60))
SET #Result= concat((#theMinutes / ((SELECT TOP 1
STUFF(WorkingHours,2,2,'') FROM dbo.WorkingDays WHERE
CountryId=#CountryId) * 60)),':' , (#theMinutes % ((SELECT TOP 1
STUFF(WorkingHours,2,2,'') FROM dbo.WorkingDays WHERE
CountryId=#CountryId) * 60)) / 60, ':', (#theMinutes % 60))
RETURN #Result
END
So where to modify to the result as
BUSINESS HOURS CREATE DATE & TIME FIRST APPLY (DATE & TIME) TAT TIME CALCULATION RESULT
08h00-17h00: 9hrs/day 12-FEB-19 14:20 13-FEB-19 14:30 00:02:40 + 00:06:30 = 00:09:10 01:00:10

Adding Parameter causing issues-No data displayed

Hi all I have a stored procedure with two parameters #Startdate and #Enddate. When i execute the procedure i get data.
Now i added a parameter and it has list of values. So i added a split function and added in the WHERE clause. Now after making the changes when i execute my SP i do not get any data. I tried commenting out the 3rd Parameter from the WHERE clause and now i see the data again. Not sure what is happening. Any advice is greatly appreciated.
I have tried different split functions and Charindex(','+cast(tableid as varchar(8000))+',', #Ids) > 0 and nothing has worked.
Thanks
NOTE: The concatenation and splitting of parameter values is a poor design for performance reasons and, most importantly, very susceptible to SQL injection attacks. Please research some alternatives. If you must proceed down this path...
There are a great many split functions out there, but I used this one here to illustrate a possible solution.
CREATE FUNCTION [dbo].[fnSplitString]
(
#string NVARCHAR(MAX),
#delimiter CHAR(1)
)
RETURNS #output TABLE(splitdata NVARCHAR(MAX)
)
BEGIN
DECLARE #start INT, #end INT
SELECT #start = 1, #end = CHARINDEX(#delimiter, #string)
WHILE #start < LEN(#string) + 1 BEGIN
IF #end = 0
SET #end = LEN(#string) + 1
INSERT INTO #output (splitdata)
VALUES(SUBSTRING(#string, #start, #end - #start))
SET #start = #end + 1
SET #end = CHARINDEX(#delimiter, #string, #start)
END
RETURN
END
GO
It's unclear, from your question, if you need to filter your results based on an int, varchar or various other data types available, but here are two options (and probably the most common).
DECLARE #TableOfData TABLE
(
ID_INT INT,
ID_VAR VARCHAR(100),
START_DATE DATETIME,
END_DATE DATETIME
)
DECLARE #StartDate DATETIME
DECLARE #EndDate DATETIME
DECLARE #Ids VARCHAR(1000)
DECLARE #Delimiter VARCHAR(1)
SET #Delimiter = ','
SET #StartDate = GETDATE()
SET #EndDate = DATEADD(HH, 1, GETDATE())
SET #Ids = '1,2,4'
--Create some test data
INSERT INTO #TableOfData
SELECT 1, '1', GETDATE(), DATEADD(MI, 1, GETDATE()) --In our window of expected results (date + id)
UNION SELECT 2, '2', GETDATE(), DATEADD(D, 1, GETDATE()) --NOT in our window of expected results b/c of date
UNION SELECT 3, '3', GETDATE(), DATEADD(MI,2, GETDATE()) --NOT in our expected results (id)
UNION SELECT 4, '4', GETDATE(), DATEADD(MI,4, GETDATE()) --In our window of expected results (date + id)
--If querying by string, expect 2 results
SELECT TD.*
FROM #TableOfData TD
INNER JOIN dbo.fnSplitString(#Ids, #Delimiter) SS
ON TD.ID_VAR = SS.splitdata
WHERE START_DATE >= #StartDate
AND END_DATE <= #EndDate
--If querying by int, expect 2 results
SELECT TD.*
FROM #TableOfData TD
INNER JOIN dbo.fnSplitString(#Ids, #Delimiter) SS
ON TD.ID_INT = CONVERT(int, SS.splitdata)
WHERE START_DATE >= #StartDate
AND END_DATE <= #EndDate
You cannot use a parameter with a list directly in your query filter. Try storing that separated data into a table variable or temp table and call that in your query or use dynamic SQL to write your query if you don't want to use table variable or temp tables.

use of IsNull with date

I have the following TSQL code:
Declare #MyDate datetime
Select #MyDate = ISNULL(T.requireddate, Convert(DateTime, '01/01/2013', 101))
from myTable T
where T.somekey = somevalue
Select #MyDate
The output is NULL. Why isn't it 01/01/2013?
Are you sure that select returns any rows?
If that select returns no rows then #MyDate would be null
Try
Select T.requireddate, ISNULL(T.requireddate, Convert(DateTime, '01/01/2013', 101))
from myTable T
where T.somekey = somevalue

how convert string variable to datetime variable in sql-server?

I'm relatively new to sql-server; I'm trying to have a start-date and end-date pulled from a form-variable as string then convert it into datetime (yyyy-mm-dd) format and I can't seem to find anything that works. Attempted code and resulting error is below. Any advice would be appreciated.
declare #startdate as varchar
declare #enddate as varchar
set #startdate=cast(#startdate as datetime)
set #enddate=cast(#enddate as datetime)
SELECT order_date, inv_no
from invoices
where order_date between #startdate and #enddate
The error I keep getting is:
Conversion failed when converting datetime from character string.
How do I fix this?
specify a length for your varchar:
declare #startdate as varchar(10)
declare #enddate as varchar(10)
set #startdate=cast(#startdate as datetime)
set #enddate=cast(#enddate as datetime)
SELECT order_date, inv_no
from invoices
where order_date between #startdate and #enddate
you don't have to cast necessarily
declare #startdate varchar(50)
declare #enddate varchar(50)
declare #start datetime = #startdate, #end datetime = #enddate
select #start, #end

How do you initialize a variable in a stored procedure with a function

How do you initialize a variable in a stored procedure with a function?
This doesn't work:
/****** Object: StoredProcedure [dbo].[usp_ShowBackpopGaps] Script Date: 05/25/2011 19:57:23 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: <Author,,Name>
-- Create date: <Create Date,,>
-- Description: <Description,,>
-- =============================================
ALTER PROCEDURE [dbo].[usp_ShowBackpopGaps]
-- Add the parameters for the stored procedure here
#StartDate datetime = DateAdd(yy, -1,getdate()),
#EndDate datetime = getdate
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
;with dateranges as(
select DateAdd(dd,-1,EtlStartDate) as DateFrom,
DateAdd(dd,1,EtlEndDate) as DateTo
from EtlJobRunStatus
where JobRunStepID like 'ETL[0-9]%' and EndTime is not null
union all
select #StartDate ,#StartDate
union all
select DateAdd(dd,-1,#EndDate),DateAdd(dd,-1,#EndDate)
)
select DateAdd(dd,-1,DateTo) as MissingFrom,
DateAdd(dd,1,NextDateFrom) as MissingTo,
DateDiff(d,DateTo, NextDateFrom) as MissingDays
from (
select distinct DateFrom, DateTo as DateTo,
(select MIN (dateFrom)
from dateranges
where DateTo > D.DateTo
) as NextDateFrom
from dateranges D
) X
where DateTo < NextDateFrom
END
GO
You can't have a function call as a parameter default.
I think you need
CREATE PROCEDURE [dbo].[usp_ShowBackpopGaps]
#StartDate DATETIME = NULL,
#EndDate DATETIME = NULL
AS
BEGIN
SET #StartDate = ISNULL(#StartDate,DATEADD(yy, -1,GETDATE()))
SET #EndDate = ISNULL(#EndDate, GETDATE())
...