在我发布关于缺少相关文档的连接项目之前,有人会确认我不是在这里遗漏了什么吗?
在format被列为字符串函数的文档页面上:
“所有内置字符串函数都是确定性的。” -字符串函数 (Transact-SQL)
format在相关页面上也没有提到不确定性:
但是,在尝试创建持久计算列时:
create table t (date_col date);
insert into t values (getdate());
alter table t add date_formatted_01 as format(date_col,'YYYY') persisted;
Run Code Online (Sandbox Code Playgroud)
返回以下错误:
无法保留表 't' 中的计算列 'date_formatted_01',因为该列是不确定的。
该文件指出
如果未提供文化参数,则使用当前会话的语言。
但添加文化论点并不会改变事情
这也失败
alter table t add date_formatted_02 as format(date_col, 'd', 'en-US' ) persisted
Run Code Online (Sandbox Code Playgroud)
reextester 演示:http ://rextester.com/ZMS22966
dbfiddle.uk 演示:http ://dbfiddle.uk/?rdbms=sqlserver_next&fiddle=7fc57d1916e901cb561b551af144aed6
函数不一定是确定性或非确定性的。有一些函数可以是确定性的,具体取决于它们的使用方式:
以下函数并不总是确定性的,但当它们以确定性方式指定时,可以在索引视图或计算列的索引中使用。
CAST并且CONVERT是这样的例子。根据您迄今为止所做的测试,我认为可以说这FORMAT并不总是确定性的,尽管它是一个字符串函数。如果你想知道它有时是否是确定性的,我能想到的唯一技术就是尝试足够多的不同方式来调用它,直到你满意为止。例如,让我们考虑FORMAT应用于数字。只有十种不同的数字输入类型:
似乎也只有九种不同的数字格式。可以尝试为所有可能的组合创建持久列。一些代码来做到这一点如下:
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;
Run Code Online (Sandbox Code Playgroud)
以下是输出示例:
对于一些输入值和文化,我无法将任何列添加到表中。我没有彻底尝试所有可能的文化,因为我在 SQL Server 中找不到它们的列表。
至少可以安全地得出结论,关于 的确定性的文档FORMAT是不正确的,因此我建议为它提交一个连接项。