format () belirsiz bir yerleşik dize işlevi ... değil mi?


10

Bununla ilgili belgelerin eksikliğine ilişkin bir bağlantı öğesi göndermeden önce, birisi burada sadece bir şey eksik olmadığımı doğrulayacak mı?

formatDize işlevi olarak listelenen dokümanlar sayfasında :

"Tüm yerleşik dize işlevleri belirleyicidir." - Dize İşlevleri (Transact-SQL)

Ayrıca, formatilgili sayfalarda belirsiz olmadıklarından da söz edilmemektedir :


Ancak, kalıcı bir hesaplanmış sütun oluşturmaya çalışırken:

create table t (date_col date); 
insert into t values (getdate());
alter table t add date_formatted_01 as format(date_col,'YYYY') persisted;

Aşağıdaki hatayı döndürür:

'T' tablosundaki hesaplanan 'date_formatted_01' sütunu kalıcı olamaz, çünkü sütun deterministik değildir.

Belgeler,

Kültür argümanı sağlanmazsa, geçerli oturumun dili kullanılır.

ama bir kültür argümanı eklemek hiçbir şeyi değiştirmez

Bu da başarısız oluyor

alter table t add date_formatted_02 as format(date_col, 'd', 'en-US' ) persisted

rextester demosu: http://rextester.com/ZMS22966

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


1
Bu aynı zamanda başarısız: alter table #t add date_formatted_01 as CONVERT(VARCHAR(20), FORMAT(date_col, 'YYYY', 'en-US')) persisted;. FORMATÖzellikle kültürü belirlerken neden belirleyici olmadığından emin değilim. date_formattedKolon olabilir edilebilir VARCHAR(20)(hala devam) kullanılarak Tetik ile ayarlanır FORMAT. Veya SQLCLR çalışır. (Yazdığım) SQL # SQLCLR kitaplığını kullanarak ( ALTER TABLE SQL#.t ADD date_formatted_03 AS SQL#.Date_Format(date_col, 'd', 'en-US') PERSISTED;tablo ve işlev sahibinin aynı olması gerektiğinden tablo SQL # 'a aittir).
Solomon Rutzky

Yanıtlar:


5

Bir işlev ille de deterministik ya da belirsiz değildir. Nasıl kullanıldıklarına bağlı olarak belirleyici olabilecek bazı işlevler vardır :

Aşağıdaki işlevler her zaman deterministik değildir, ancak belirli bir şekilde belirtildiklerinde hesaplanmış sütunlardaki dizinlenmiş görünümlerde veya dizinlerde kullanılabilir.

CASTve CONVERTbu örnekler. Şimdiye kadar yaptığınız testlere dayanarak, FORMATbir dize işlevi olmasına rağmen, her zaman deterministik olmadığını söylemenin adil olduğunu düşünüyorum . Bazen deterministik olup olmadığını bilmek istiyorsanız, düşünebildiğim tek teknik, memnun olana kadar onu aramak için yeterince farklı yollar denemektir. Örneğin, FORMATsayılara uygulanmış olarak düşünelim . Yalnızca on farklı sayısal giriş türü vardır :

sayısal giriş türleri

Ayrıca sadece dokuz farklı sayısal biçim var . Tüm olası kombinasyonlar için kalıcı sütunlar oluşturmaya çalışmak mümkündür. Bunu yapmak için bazı kodlar aşağıdadır:

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;

İşte çıktıdan bir örnek:

test kodu çıkışı

Birkaç girdi değeri ve kültür için tabloya eklenecek sütunlardan hiçbirini alamadım. SQL Server'da bir listesini bulamadığım için olası tüm kültürleri kapsamlı bir şekilde denemedim.

En azından, determinizmiyle ilgili belgelerin FORMATyanlış olduğu sonucuna varmak güvenli görünüyor , bu yüzden bunun için bir bağlantı öğesi göndermenizi tavsiye ederim.



1

Ben sqlserver düzenli bir kullanıcı değilim, bu yüzden yanlış olabilir, ama benim tahminim bu biçim bir dize işlevi değildir. Belgelere göre:

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

biçim bağımsız değişken olarak bir tarih türü veya sayısal bir tür alır. Tek yapmak istediğiniz bir tarihin yıl bölümünü almaksa yıl işlevini kullanamaz mısınız?

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

dize temsili istiyorsanız:

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

1
Dokümanlarda dize işlevi olarak listelenir. i.stack.imgur.com/aj0T2.png
Martin Smith

1
@MartinSmith, ilginç. Şahsen ben sezgisel karşı buluyorum ve aynı zamanda mantıksal olarak "Tüm yerleşik dize fonksiyonları deterministiktir."
Lennart

@Lennart Örneğe alternatifi takdir ediyorum, ancak örnek önemli değildi.
SqlZim

1
@SqlZim, örneğinizin sadece bir örnek olduğunu anladım, ancak her ihtimale karşı bir alternatif ekledim. Sorunuzun tam olarak ne olduğundan emin değilim, biçimin bir dize işlevi olup olmadığı, deterministik olsun ya da olmasın, ya da tüm bunlar kötü belgeleniyor mu?
Lennart
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.