【问题标题】:Scalar function is non-deterministic标量函数是非确定性的
【发布时间】:2022-01-17 20:47:33
【问题描述】:

我想保留这个字段,但不知道为什么它是不确定的。

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

这将返回 0

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

使用 SQL Server 2017

【问题讨论】:

  • 您的(日期和)时间字符串的隐式转换很可能是候选对象。这是不允许的。它必须是显式并带有样式代码。
  • 我也对那个表达感到困惑。您将 days 添加到 '08:00:00',但这显然是 time,而不是日期和时间。

标签: sql-server tsql non-deterministic


【解决方案1】:

正如我所提到的,问题是您使用(日期和)时间值的隐式转换。根据documentation:

以下函数并不总是确定性的,但当它们以确定性方式指定时,可用于索引视图或计算列的索引。

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.

在您的函数中,您有隐式转换,例如 '08:00:00' 到 datetime。你需要明确:

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')

【讨论】:

  • 成功了,谢谢!早上 8 点约会的表达是我在这里找到的,它很有效,所以我没有多想。
猜你喜欢
  • 2013-12-13
  • 1970-01-01
  • 2016-05-14
  • 1970-01-01
  • 1970-01-01
  • 2014-03-22
  • 2014-08-11
  • 1970-01-01
相关资源
最近更新 更多