प्रारूप () एक nondeterministic अंतर्निहित स्ट्रिंग फ़ंक्शन है ... सही है?


10

इससे पहले कि मैं इस बारे में दस्तावेज़ीकरण की कमी के बारे में एक कनेक्ट आइटम पोस्ट करूं, क्या कोई पुष्टि करेगा कि मैं यहां कुछ याद नहीं कर रहा हूं?

डॉक्स पृष्ठ पर जहां formatएक स्ट्रिंग फ़ंक्शन के रूप में सूचीबद्ध किया गया है:

"सभी अंतर्निहित स्ट्रिंग फ़ंक्शंस नियतात्मक हैं।" - स्ट्रिंग फ़ंक्शंस (लेनदेन-एसक्यूएल)

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;

निम्न त्रुटि देता है:

तालिका 't' में कंप्यूट किए गए कॉलम 'date_formatted_01' को बरकरार नहीं रखा जा सकता है क्योंकि कॉलम गैर-निर्धारक है।

प्रलेखन में कहा गया है कि

यदि संस्कृति तर्क प्रदान नहीं किया जाता है, तो वर्तमान सत्र की भाषा का उपयोग किया जाता है।

लेकिन संस्कृति तर्क जोड़ने से चीजें नहीं बदलतीं

यह भी विफल

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


1
यह भी विफल रहता है: alter table #t add date_formatted_01 as CONVERT(VARCHAR(20), FORMAT(date_col, 'YYYY', 'en-US')) persisted;। निश्चित नहीं है कि FORMATनियतात्मक क्यों नहीं है, खासकर जब संस्कृति को निर्दिष्ट करना। date_formattedस्तंभ सकते हो VARCHAR(20)(अभी भी कायम) और का उपयोग कर उत्प्रेरक के माध्यम से सेट FORMAT। या SQLCLR काम करता है। SQL # SQLCLR लाइब्रेरी (जो मैंने लिखा था) का उपयोग करते हुए , आप कर सकते हैं ALTER TABLE SQL#.t ADD date_formatted_03 AS SQL#.Date_Format(date_col, 'd', 'en-US') PERSISTED;(तालिका का स्वामित्व SQL # के पास है क्योंकि तालिका और फ़ंक्शन स्वामी को समान होने की आवश्यकता है)।
सोलोमन रटज़की

जवाबों:


5

एक फ़ंक्शन आवश्यक रूप से नियतात्मक या नॉन्डेटेरमिनिस्टिक नहीं है। कुछ कार्य हैं जो यह निर्धारित कर सकते हैं कि उनका उपयोग कैसे किया जाता है :

निम्नलिखित कार्य हमेशा नियतात्मक नहीं होते हैं, लेकिन जब वे निर्धारक तरीके से निर्दिष्ट होते हैं, तो गणना किए गए स्तंभों पर अनुक्रमित दृश्यों या अनुक्रमित में उपयोग किया जा सकता है।

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 सर्वर के भीतर उनकी सूची नहीं पा सकता हूं।

कम से कम यह निष्कर्ष निकालना सुरक्षित है कि नियतत्ववाद के बारे में प्रलेखन FORMATगलत है, इसलिए मैं इसके लिए एक कनेक्ट आइटम प्रस्तुत करने की सलाह दूंगा।


6

FORMATप्रलेखन अब कर दिया गया है अद्यतन (आपका के जवाब में कनेक्ट आइटम कहने के लिए):

FORMATसमारोह गैर नियतात्मक है।

इसी तरह, स्ट्रिंग फ़ंक्शंस (लेनदेन-एसक्यूएल) में अब शामिल हैं:

सभी अंतर्निहित स्ट्रिंग कार्य FORMATनिर्धारक हैं।


1

मैं sqlserver का नियमित उपयोगकर्ता नहीं हूं, इसलिए मुझसे गलती हो सकती है, लेकिन मेरा अनुमान है कि प्रारूप कोई स्ट्रिंग फ़ंक्शन नहीं है। प्रलेखन के अनुसार:

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

स्वरूप या तो दिनांक प्रकार या एक संख्यात्मक प्रकार तर्क के रूप में लेता है। यदि आप सभी को डेट का वर्ष-भाग हड़पना चाहते हैं, तो आप वर्ष कार्य का उपयोग नहीं कर सकते?

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
यह डॉक्स में एक स्ट्रिंग फ़ंक्शन के रूप में सूचीबद्ध है। i.stack.imgur.com/aj0T2.png
मार्टिन स्मिथ

1
@ मर्टिनस्मिथ, दिलचस्प। व्यक्तिगत रूप से मुझे यह सहज ज्ञान युक्त लगता है और यह तार्किक रूप से असंगत भी हो जाता है "सभी अंतर्निहित स्ट्रिंग फ़ंक्शंस नियतात्मक हैं।"
लेनार्ट

@ मैं उदाहरण के विकल्प की सराहना करता हूं, लेकिन उदाहरण महत्वपूर्ण नहीं था।
स्क्लज़िम

1
@ SqlZim, मुझे लगा कि आपका उदाहरण सिर्फ एक उदाहरण है, लेकिन मैंने सिर्फ एक विकल्प जोड़ा है। मुझे यकीन नहीं है कि आपका प्रश्न वास्तव में क्या है, क्या यह है कि प्रारूप एक स्ट्रिंग फ़ंक्शन है या नहीं, चाहे यह नियतात्मक है या नहीं, या क्या यह सब बुरी तरह से प्रलेखित है?
लेनार्ट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.