Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Scalar function is non-deterministic

I’d like to persist this field but can’t figure out why it’s non-deterministic.

CREATE FUNCTION GetServiceMinutes
(
    -- Add the parameters for the function here
    @StartDate datetime,
    @EndDate datetime
)
RETURNS int WITH SCHEMABINDING
AS
BEGIN
    DECLARE @Result int

    SET @StartDate = CASE WHEN DATEPART(HOUR, @StartDate) < 8 THEN DATEADD(DAY, DATEDIFF(DAY, 0, @StartDate), '08:00:00')  ELSE @StartDate END
    SET @EndDate = CASE WHEN DATEPART(HOUR, @EndDate) >= 17 THEN DATEADD(DAY, DATEDIFF(DAY, 0, @EndDate), '17:00:00') ELSE @EndDate END
    
    SET @Result = 
         CASE WHEN DATEPART(DAY, @StartDate) != DATEPART(DAY, @EndDate) THEN 1000
              WHEN DATEPART(HOUR, @EndDate) < 8 THEN 0
              WHEN DATEPART(HOUR, @StartDate) >= 17 THEN 0
              ELSE DATEDIFF(MINUTE, @StartDate, @EndDate)
    END
    
    RETURN @Result

END
GO

This returns 0

SELECT OBJECTPROPERTY(OBJECT_ID('[dbo].GetServiceMinutes'), 'IsDeterministic')

Using SQL Server 2017

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

The problem, as I alluded to, is your implicit conversions with (date and) time values. Per the documentation:

The following functions are not always deterministic, but can be used in indexed views or indexes on computed columns when they are specified in a deterministic manner.

Function Comments
all aggregate functions All aggregate functions are deterministic unless they are specified with the OVER and ORDER BY clauses. For a list of these functions, see Aggregate Functions (Transact-SQL).
CAST Deterministic unless used with datetime, smalldatetime, or sql_variant.
CONVERT Deterministic unless one of these conditions exists:
Source type is sql_variant.
Target type is sql_variant and its source type is nondeterministic.
Source or target type is datetime or smalldatetime, the other source or target type is a character string, and a nondeterministic style is specified. To be deterministic, the style parameter must be a constant. Additionally, styles less than or equal to 100 are nondeterministic, except for styles 20 and 21. Styles greater than 100 are deterministic, except for styles 106, 107, 109 and 113.

In your function you have implicit casting, for example '08:00:00' to a datetime. You need to be explicit:

CREATE FUNCTION dbo.GetServiceMinutes
(
    -- Add the parameters for the function here
    @StartDate datetime,
    @EndDate datetime
)
RETURNS int WITH SCHEMABINDING
AS
BEGIN
    DECLARE @Result int

    SET @StartDate = CASE WHEN DATEPART(HOUR, @StartDate) < 8 THEN DATEADD(DAY, DATEDIFF(DAY, 0, @StartDate), CONVERT(datetime,'1900-01-01T08:00:00',126))  ELSE @StartDate END
    SET @EndDate = CASE WHEN DATEPART(HOUR, @EndDate) >= 17 THEN DATEADD(DAY, DATEDIFF(DAY, 0, @EndDate), CONVERT(datetime,'1900-01-01T17:00:00',126)) ELSE @EndDate END
    
    SET @Result = 
         CASE WHEN DATEPART(DAY, @StartDate) != DATEPART(DAY, @EndDate) THEN 1000
              WHEN DATEPART(HOUR, @EndDate) < 8 THEN 0
              WHEN DATEPART(HOUR, @StartDate) >= 17 THEN 0
              ELSE DATEDIFF(MINUTE, @StartDate, @EndDate)
    END
    
    RETURN @Result

END
GO

SELECT OBJECTPROPERTY(OBJECT_ID('[dbo].GetServiceMinutes'), 'IsDeterministic')
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading