首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >format()是一个不确定的内置字符串函数.对吗?

format()是一个不确定的内置字符串函数.对吗?
EN

Database Administration用户
提问于 2017-05-27 13:03:25
回答 3查看 1.5K关注 0票数 10

在我发布关于这方面缺乏文档的连接项目之前,会有人确认我不是简单地遗漏了一些东西吗?

在docs页面上,format被列为字符串函数:

“所有内置的字符串函数都是确定性的。”- 字符串函数(Transact-SQL)

也没有提到format在相关页面上是不确定的:

但是,当尝试创建持久化计算列时:

代码语言:javascript
复制
create table t (date_col date); 
insert into t values (getdate());
alter table t add date_formatted_01 as format(date_col,'YYYY') persisted;

返回以下错误:

表't‘中的计算列'date_formatted_01’不能持久化,因为该列是不确定的。

文件指出,

如果不提供区域性参数,则使用当前会话的语言。

但是添加一个文化参数不会改变任何事情

这也失败了

代码语言:javascript
复制
alter table t add date_formatted_02 as format(date_col, 'd', 'en-US' ) persisted

rextester演示:http://rextester.com/ZMS22966

dbfiddle.uk演示:http://dbfiddle.uk/?rdbms=sqlserver_next&fiddle=7fc57d1916e901cb561b551af144aed6

EN

回答 3

Database Administration用户

回答已采纳

发布于 2017-05-27 18:21:01

函数不一定是确定性的或非确定性的。有一些函数可以是确定性的取决于它们的使用方式

以下函数并不总是确定性的,但如果以确定性方式指定,则可以在计算列上的索引视图或索引中使用。

CASTCONVERT就是这样的例子。基于您到目前为止所做的测试,我认为可以公平地说,FORMAT并不总是确定性的,尽管它是一个字符串函数。如果你想知道它有时是否是确定性的,我能想到的唯一的方法就是尝试足够的不同的方法来调用它,直到你满意为止。例如,让我们将FORMAT应用于数字。只有十种不同的数字输入类型

似乎也只有九种不同的数字格式。可以尝试为所有可能的组合创建持久化列。这样做的一些代码如下:

代码语言:javascript
复制
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;

以下是输出的示例:

对于一些输入值和区域性,我无法将任何列添加到表中。我没有穷尽地尝试所有可能的区域性,因为我在Server中找不到它们的列表。

至少可以得出这样的结论:关于FORMAT的确定性的文档是不正确的,所以我建议为它提交一个连接项。

票数 5
EN

Database Administration用户

发布于 2017-08-17 03:14:19

FORMAT文档现在已经是已更新 (作为对您的连接项的响应)来表示:

FORMAT函数是不确定的。

同样,字符串函数(Transact-SQL)现在包括:

FORMAT外,所有内置字符串函数都是确定性的。

票数 7
EN

Database Administration用户

发布于 2017-05-27 14:06:40

我不是sqlserver的常规用户,所以我可能弄错了,但我的猜测是,这种格式不是字符串函数。根据文件:

https://learn.microsoft.com/en-us/sql/t-sql/functions/format-transact-sql

格式采用日期类型或数字类型作为参数。如果你想要做的只是抓取一年--日期的一部分,你不能使用年份函数吗?

代码语言:javascript
复制
alter table t 
    add date_formatted_01 as year(date_col) persisted;

如果您想要字符串表示:

代码语言:javascript
复制
alter table t 
    add date_formatted_01 as cast(year(date_col) as char(4)) persisted;
票数 1
EN
页面原文内容由Database Administration提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://dba.stackexchange.com/questions/174739

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档