Funkcja niekoniecznie musi być deterministyczna lub niedeterministyczna. Istnieje kilka funkcji, które mogą być deterministyczne w zależności od sposobu ich użycia :
Poniższe funkcje nie zawsze są deterministyczne, ale można ich używać w widokach indeksowanych lub indeksach w kolumnach obliczeniowych, jeśli są one określone w sposób deterministyczny.
CASTi CONVERTsą takimi przykładami. Bazując na testach, które przeprowadziłeś do tej pory, myślę, że można śmiało powiedzieć, że FORMATnie zawsze jest to deterministyczne, mimo że jest funkcją strunową. Jeśli chcesz wiedzieć, czy czasami jest to deterministyczne, jedyną techniką, jaką mogę wymyślić, jest wypróbowanie wystarczająco wielu różnych sposobów nazywania go, dopóki nie będziesz zadowolony. Rozważmy FORMATna przykład, w odniesieniu do liczb. Istnieje tylko dziesięć różnych typów wprowadzania numerycznego :

Wydaje się również, że istnieje tylko dziewięć różnych formatów numerycznych . Można spróbować utworzyć trwałe kolumny dla wszystkich możliwych kombinacji. Poniżej znajduje się kod do zrobienia tego:
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;
Oto próbka danych wyjściowych:

Nie byłem w stanie uzyskać żadnej kolumny, która mogłaby zostać dodana do tabeli dla kilku wartości wejściowych i kultur. Nie wypróbowałem wyczerpująco wszystkich możliwych kultur, ponieważ nie mogę znaleźć ich listy w SQL Server.
FORMATPrzynajmniej wydaje się bezpiecznie stwierdzić, że dokumentacja dotycząca determinizmu jest niepoprawna, dlatego zaleciłbym przesłanie w tym celu elementu Connect.
alter table #t add date_formatted_01 as CONVERT(VARCHAR(20), FORMAT(date_col, 'YYYY', 'en-US')) persisted;. Nie jestem pewien, dlaczegoFORMATnie jest deterministyczny, szczególnie przy określaniu kultury.date_formattedKolumna może byćVARCHAR(20)(jeszcze utrzymywały) i ustawiona za pomocą wyzwalaczaFORMAT. Lub działa SQLCLR. Korzystając z biblioteki SQL # SQLCLR (którą napisałem), możesz to zrobićALTER TABLE SQL#.t ADD date_formatted_03 AS SQL#.Date_Format(date_col, 'd', 'en-US') PERSISTED;(tabela jest własnością SQL #, ponieważ właściciel tabeli i funkcji musi być taki sam).