Why is this type conversion rejected as non-deterministic for a PERSISTED
computed column in return tables of user-defined functions (UDF) in SQL Server?
CREATE FUNCTION MyTimeIntervalFunction(@Param1 INT)
RETURNS @MyTimeInterval TABLE
(
StartUtc DATETIME NOT NULL PRIMARY KEY
,EndUtc DATETIME NOT NULL
,DateUtc AS CONVERT(DATE, StartUtc) PERSISTED
)
AS BEGIN
--do stuff
RETURN
END
Note this is not converting to or from a string representation, so I don't know why it doesn't work because globalization/region stuff should be irrelevant.
This works outside of a UDF (including stored procedures):
DECLARE @MyTimeInterval TABLE
(
StartUtc DATETIME NOT NULL PRIMARY KEY
,EndUtc DATETIME NOT NULL
,DateUtc AS CONVERT(DATE, StartUtc) PERSISTED
)
INSERT INTO @MyTimeInterval(StartUtc, EndUtc)
VALUES ('2018-01-01', '2018-01-02')
SELECT * FROM @MyTimeInterval
It seems that adding WITH SCHEMABINDING
to the UDF definition shuts it up, but I don't understand why, because it looks like that only marks the function output as deterministic based on input parameters. And I have to do other non-deterministic stuff in my function, so it is not a candidate workaround.
Wonky string manipulation could also be a workaround, but is not preferable. Style 126 for ISO-8601 on CONVERT
is still non-deterministic according to SQL Server. It seems the only option is to abandon use of persisted computed columns?
As mentioned at the beginning of this somewhat related answer, not specifying WITH SCHEMABINDING
means SQL Server skips checks on such things as determinism and data access.
Since PERSISTED
in a computer column requires the "computed column expression" to be deterministic and SQL Server skips any checks on whether or not it actually is deterministic, it won't be allowed. The same error would occur even if you had something as simple as i AS 1 PERSISTED
.
(This is unrelated to whether everything in the function itself is deterministic.)
All that said, using PERSISTED
in a TVF doesn't actually add anything to the function, as far as I know.