Une fonction n'est pas nécessairement déterministe ou non déterministe. Certaines fonctions peuvent être déterministes en fonction de leur utilisation :
Les fonctions suivantes ne sont pas toujours déterministes, mais peuvent être utilisées dans des vues indexées ou des index sur des colonnes calculées lorsqu'elles sont spécifiées de manière déterministe.
CASTet CONVERTsont de tels exemples. Sur la base des tests que vous avez effectués jusqu'à présent, je pense qu'il est juste de dire que ce FORMATn'est pas toujours déterministe, bien qu'il s'agisse d'une fonction de chaîne. Si vous voulez savoir si c'est parfois déterministe, la seule technique à laquelle je peux penser est d'essayer suffisamment de façons différentes de l'appeler jusqu'à ce que vous soyez satisfait. Par exemple, considérons FORMATcomme appliqué aux nombres. Il n'y a que dix types d'entrées numériques différents :

Il semble également qu'il n'y ait que neuf formats numériques différents . Il est possible d'essayer de créer des colonnes persistantes pour toutes les combinaisons possibles. Un code pour le faire est ci-dessous:
DECLARE @FormatValue INT = 76767; -- change this if you want
DECLARE @FormatCulture VARCHAR(10) = 'en-US'; -- change this if you want
DECLARE @Format VARCHAR(1);
DECLARE @FormatType VARCHAR(10);
DECLARE @SQLForColumn VARCHAR(200);
DECLARE @TestNumber INT = 0;
BEGIN
DROP TABLE IF EXISTS dbo.TargetTable;
CREATE TABLE dbo.TargetTable (ID INT);
DROP TABLE IF EXISTS #ColumnAddResults;
CREATE TABLE #ColumnAddResults (
FormatType VARCHAR(10),
[Format] VARCHAR(1),
Succeeded VARCHAR(1),
ErrorMessage VARCHAR(1000)
);
drop table if exists #Types;
create table #Types (FormatType VARCHAR(10));
INSERT INTO #Types VALUES
('bigint'), ('int'), ('smallint'), ('tinyint'), ('decimal')
, ('numeric'), ('float'), ('real'), ('smallmoney'), ('money');
drop table if exists #Formats;
create table #Formats ([Format] VARCHAR(1));
INSERT INTO #Formats VALUES
('C'), ('D'), ('E'), ('F'), ('G'), ('N'), ('P'), ('R'), ('X');
DECLARE format_statements CURSOR LOCAL FAST_FORWARD FOR
SELECT #Types.FormatType, #Formats.[Format]
FROM #Formats
CROSS JOIN #Types;
OPEN format_statements;
FETCH NEXT FROM format_statements
INTO @FormatType, @Format;
WHILE @@FETCH_STATUS = 0
BEGIN
SET @TestNumber = @TestNumber + 1;
SET @SQLForColumn = 'alter table dbo.TargetTable add NewColumn' + CAST(@TestNumber AS VARCHAR(10))
+ ' as FORMAT(CAST(' + CAST(@FormatValue AS VARCHAR(10)) + ' AS ' + @FormatType + '), '
+ '''' + @Format + ''', ''' + @FormatCulture + ''') persisted';
BEGIN TRY
EXEC (@SQLForColumn);
INSERT INTO #ColumnAddResults VALUES (@FormatType, @Format, 'Y', NULL);
END TRY
BEGIN CATCH
INSERT INTO #ColumnAddResults VALUES (@FormatType, @Format, 'N', ERROR_MESSAGE());
END CATCH;
PRINT @SQLForColumn;
FETCH NEXT FROM format_statements
INTO @FormatType, @Format;
END;
CLOSE format_statements;
DEALLOCATE format_statements;
SELECT * FROM dbo.TargetTable;
SELECT * FROM #ColumnAddResults;
DROP TABLE #ColumnAddResults;
END;
Voici un échantillon de la sortie:

Je n'ai pu obtenir aucune des colonnes à ajouter au tableau pour quelques valeurs d'entrée et cultures. Je n'ai pas essayé de façon exhaustive toutes les cultures possibles car je ne trouve pas de liste d'entre elles dans SQL Server.
Au minimum, il semble sûr de conclure que la documentation concernant le déterminisme de FORMATest incorrecte, donc je recommanderais de lui soumettre un élément de connexion.
alter table #t add date_formatted_01 as CONVERT(VARCHAR(20), FORMAT(date_col, 'YYYY', 'en-US')) persisted;. Je ne sais pas pourquoiFORMATn'est pas déterministe, surtout quand on spécifie la culture. Ladate_formattedcolonne peut êtreVARCHAR(20)(toujours persistante) et définie via Trigger à l'aide deFORMAT. Ou SQLCLR fonctionne. En utilisant la bibliothèque SQL # SQLCLR (que j'ai écrite), vous pouvez le faireALTER TABLE SQL#.t ADD date_formatted_03 AS SQL#.Date_Format(date_col, 'd', 'en-US') PERSISTED;(la table appartient à SQL # car le propriétaire de la table et de la fonction doit être le même).