AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 174739
Accepted
SqlZim
SqlZim
Asked: 2017-05-28 05:03:25 +0800 CST2017-05-28 05:03:25 +0800 CST 2017-05-28 05:03:25 +0800 CST

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

  • 772

在我发布关于缺少相关文档的连接项目之前,有人会确认我不仅仅是在这里遗漏了什么吗?

在format被列为字符串函数的文档页面上:

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

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

  • 确定性和非确定性函数
  • 格式 (Transact-SQL)

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

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”,因为该列是不确定的。

该文档指出

如果未提供 culture 参数,则使用当前会话的语言。

但添加文化论点并没有改变事情

这也失败了

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

sql-server
  • 3 3 个回答
  • 1384 Views

3 个回答

  • Voted
  1. Paul White
    2017-08-17T19:14:19+08:002017-08-17T19:14:19+08:00

    该FORMAT文档现已更新(响应您的Connect 项目)说:

    该FORMAT函数是不确定的。

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

    FORMAT除了确定性的所有内置字符串函数。

    • 7
  2. Best Answer
    Joe Obbish
    2017-05-28T10:21:01+08:002017-05-28T10:21:01+08:00

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

    以下函数并不总是确定性的,但可以在以确定性方式指定时用于索引视图或计算列的索引。

    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;
    

    这是输出示例:

    测试代码输出

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

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

    • 5
  3. Lennart - Slava Ukraini
    2017-05-28T06:06:40+08:002017-05-28T06:06:40+08:00

    我不是 sqlserver 的普通用户,所以我可能弄错了,但我的猜测是 format 不是字符串函数。根据文档:

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

    format 采用日期类型或数字类型作为参数。如果你只想获取日期的年份部分,你不能使用年份函数吗?

    alter table t 
        add date_formatted_01 as year(date_col) persisted;
    

    如果你想要一个字符串表示:

    alter table t 
        add date_formatted_01 as cast(year(date_col) as char(4)) persisted;
    
    • 1

相关问题

  • SQL Server - 使用聚集索引时如何存储数据页

  • 我需要为每种类型的查询使用单独的索引,还是一个多列索引可以工作?

  • 什么时候应该使用唯一约束而不是唯一索引?

  • 死锁的主要原因是什么,可以预防吗?

  • 如何确定是否需要或需要索引

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve