When creating an indexed view which uses the built-in function FORMATMESSAGE, I get an error (below), that FORMATMESSAGE is non-deterministic. Understandably, the view cannot be materialised, and this is presumably because the output of FORMATMESSAGE depends on localisation info, so doesn't always give the same output for the same parameters.
I've tried to find a way to pass a specific locale to FORMATMESSAGE to make it deterministic by using sys.messages instead of a literal format string, with no success.
However, the latest MS info about Deterministic and Nondeterministic Functions doesn't specifically say that FORMATMESSAGE is non-deteministic. Thus,
Has anyone found a way to use FORMATMESSAGE in an indexed view?
Here is my simplified test code:
SET ANSI_NULLS, QUOTED_IDENTIFIER, ANSI_PADDING ON
GO ----------------------------------------------------------------
CREATE TABLE dbo.Extensions(
ID INT IDENTITY(1,1) NOT NULL,
Name VARCHAR(50) NULL,
ExtNo INTEGER NOT NULL,
CONSTRAINT PK_Test PRIMARY KEY CLUSTERED (ID ASC)
)
GO ----------------------------------------------------------------
INSERT dbo.Extensions (Name, ExtNo)
VALUES ('New York', 55),
('San Francisco', 6),
('Paris', 4);
GO ----------------------------------------------------------------
CREATE VIEW dbo.vwExtensions
WITH SCHEMABINDING AS
SELECT
ID,
FORMATMESSAGE ('%s Extension %03i', Name, ExtNo) AS ExtensionName
FROM
dbo.Extensions
GO ----------------------------------------------------------------
So far, so good. SELECT * FROM dbo.vwExtensions yields the correct results:
But the whole point of this is to make the view indexed (so it gets materialised, i.e. the results are calculated in advance and persisted in the view by SQL Server - Speed, man!). However,
CREATE UNIQUE CLUSTERED INDEX IX_Extension ON dbo.vwExtensions (ID)
gives an error:
Cannot create index on view 'TEST_DB.dbo.vwExtensions'. The function 'formatmessage' yields nondeterministic results. Use a deterministic system function, or ...
Note: I'm not looking for a computed column solution, for other reasons not important here. (That wouldn't allow the persisted attribute of the computed column to be set true in any case, for exactly the same reasons as above).
Edit: Should add here - I need to use FORMATMESSAGE (or some deterministic alternative), rather than CONCAT (RIGHT (... etc, since the format string is also stored in a table, rather than hard-coded, as indicated here. The simplified version of my code above does not indicate that.

FORMATMESSAGEis never deterministic simply by virtue of not being on the list. What you want can be achieved by combining ordinary string manipulation functions (e.g.RIGHT('000' + CONVERT(VARCHAR(20), ExtNo), 3)), which is significantly more clumsy but hey, deterministic. Custom CLR scalar-valued functions can also be marked deterministic, but that seems overkill here.FORMATbe counted as deterministic if (and only if) thecultureparameter is explicitly supplied. That sounds like the sort of thing that could be useful (and is more general thanFORMATMESSAGE). I don't know if the .NET runtime can be relied on to be deterministic in this regard, though (and not defer to the OS for some choices, which would possibly make things nondeterministic again).FORMATMESSAGEunder the covers, as much as that's asking for trouble.) You could, conceivably, write a function capable of parsing and formatting such strings in pure T-SQL, but it'd be an exercise in suffering, even if you limited the valid formatting options.RIGHT (... CONVERT ( ...for now. Writing a custom CLR function is too complicated for the time being for my project, so will have to go for the simpler, less flexible option.