"SELECT POWER (10.0, 38.0)?" एक अंकगणितीय अतिप्रवाह त्रुटि क्यों करता है?


15

मैं अपने IDENTITYओवरफ्लो चेक स्क्रिप्ट को अपडेट कर रहा हूं और कॉलम के लिए खाता हूंDECIMALNUMERIC IDENTITY

चेक के हिस्से के रूप में मैं हर IDENTITYकॉलम के लिए डेटा प्रकार की सीमा के आकार की गणना करता हूं ; मैं इसका उपयोग यह गणना करने के लिए करता हूं कि उस सीमा का कितना प्रतिशत समाप्त हो गया है। के लिए DECIMALऔर NUMERIC उस श्रेणी का आकार वह2 * 10^p - 2 जगह है जहांp है सटीक है।

मैंने टेबलों के साथ DECIMALऔर NUMERIC IDENTITYस्तंभों का एक समूह बनाया और उनकी श्रेणियों की गणना करने का प्रयास किया:

SELECT POWER(10.0, precision)
FROM sys.columns
WHERE 
       is_identity = 1
   AND type_is_decimal_or_numeric
;

यह निम्नलिखित त्रुटि फेंक दिया:

Msg 8115, Level 16, State 6, Line 1
Arithmetic overflow error converting float to data type numeric. 

मैंने इसे IDENTITYटाइप के स्तंभों तक सीमित कर दिया DECIMAL(38, 0)(यानी अधिकतम परिशुद्धता के साथ), इसलिए मैंने POWER()उस मान पर सीधे गणना की कोशिश की ।

निम्नलिखित सभी प्रश्न

SELECT POWER(10.0, 38.0);
SELECT CONVERT(FLOAT, (POWER(10.0, 38.0)));
SELECT CAST(POWER(10.0, 38.0) AS FLOAT);

उसी त्रुटि के परिणामस्वरूप भी।

  • SQL सर्वर आउटपुट POWER()के प्रकार को परिवर्तित करने का प्रयास क्यों करता है , जो कि प्रकार का है FLOAT, NUMERIC(विशेषकर तब जब FLOATइसका उच्च स्तर हो )?
  • मैं गतिशील रूप से DECIMALया NUMERICसभी संभावित पूर्वाग्रहों के लिए कॉलम की श्रेणी की गणना कैसे कर सकता हूं (सहित p = 38, निश्चित रूप से)?

जवाबों:


18

से POWERप्रलेखन :

वाक्य - विन्यास

POWER ( float_expression , y )

तर्क

float_expression
एक प्रकार की नाव या एक प्रकार की अभिव्यक्ति है जिसे अस्थायी रूप से नाव में परिवर्तित किया जा सकता है ।

y फ्लोट_फैप्रेशन
को बढ़ाने की शक्ति हैy बिट को छोड़कर, सटीक संख्यात्मक या अनुमानित संख्यात्मक डेटा प्रकार श्रेणी की अभिव्यक्ति हो सकती है डेटा प्रकार ।

वापसी के प्रकार

फ्लोट_फ्रेम में सबमिट किए गए समान प्रकार देता है । उदाहरण के लिए, यदि दशमलव (2,0) को float_expression के रूप में प्रस्तुत किया जाता है, तो लौटा हुआ परिणाम दशमलव (2,0) है।


floatयदि आवश्यक हो तो पहला इनपुट निहित है।

आंतरिक गणना floatमानक सी रनटाइम लाइब्रेरी (सीआरटी) फ़ंक्शन द्वारा अंकगणित का उपयोग करके की जाती है pow

floatसे उत्पादन powतो बाएं हाथ के प्रकार पर वापस डाली है संकार्य (होने के लिए निहितnumeric(3,1) है जब आप शाब्दिक मूल्य 10.0 उपयोग करें)।

floatआपके मामले में एक स्पष्ट कार्य का उपयोग करना :

SELECT POWER(1e1, 38);
SELECT POWER(CAST(10 as float), 38.0);

10 38 के लिए एक सटीक परिणाम को SQL सर्वर में संग्रहीत नहीं किया जा सकता है decimal/numericक्योंकि इसके लिए 39 अंकों की शुद्धता की आवश्यकता होती है (1 के बाद 38 शून्य)। अधिकतम परिशुद्धता 38 है।


23

मार्टिन के किसी भी जवाब से ध्यान हटाने के बजाय, मैं अपने बाकी के निष्कर्षों को POWER()यहां जोड़ दूंगा ।

अपने घुटनों पर पकड़ो।

प्रस्तावना

सबसे पहले, मैं आपके लिए A, MSDN प्रलेखनPOWER() प्रदर्शित करता हूं :

वाक्य - विन्यास

POWER ( float_expression , y )

तर्क

float_expression एक प्रकार की फ्लोट की अभिव्यक्ति है या एक प्रकार की जिसे अस्थायी रूप से फ्लोट में परिवर्तित किया जा सकता है।

वापसी के प्रकार

के रूप में ही float_expression

आप उस अंतिम पंक्ति को पढ़ने से निष्कर्ष निकाल सकते हैं जो कि POWER()रिटर्न प्रकार है FLOAT, लेकिन फिर से पढ़ें। float_expression"टाइप फ़्लोट का या एक प्रकार का जिसे फ़्लोट में रूपांतरित किया जा सकता है"। इसलिए, इसके नाम के बावजूद, float_expressionवास्तव में ए FLOAT, ए DECIMAL, या ए हो सकता है INT। चूंकि इनका आउटपुट POWER()समान है float_expression, इसलिए यह भी उन प्रकारों में से एक हो सकता है।

इसलिए हमारे पास वापसी प्रकार के साथ एक स्केलर फ़ंक्शन है जो इनपुट पर निर्भर करता है। यह हो सकता है?

टिप्पणियों

मैं आपके सामने B को प्रदर्शित करता हूं, जो यह प्रदर्शित POWER()करता है कि इसके इनपुट के आधार पर इसके आउटपुट को विभिन्न डेटा प्रकारों में डाला जाता है

SELECT 
    POWER(10, 3)             AS int
  , POWER(1000000000000, 3)  AS numeric0     -- one trillion
  , POWER(10.0, 3)           AS numeric1
  , POWER(10.12305, 3)       AS numeric5
  , POWER(1e1, 3)            AS float
INTO power_test;

EXECUTE sp_help power_test;

DROP TABLE power_test;

प्रासंगिक परिणाम हैं:

Column_name    Type      Length    Prec     Scale
-------------------------------------------------
int            int       4         10       0
numeric0       numeric   17        38       0
numeric1       numeric   17        38       1
numeric5       numeric   17        38       5
float          float     8         53       NULL

जो प्रतीत हो रहा है, वह यह है कि इसमें शामिल होने वाले सबसे छोटे प्रकार में POWER()डाली float_expressionजाती है, जिसमें शामिल नहीं है BIGINT

इसलिए, SELECT POWER(10.0, 38);एक अतिप्रवाह त्रुटि के साथ विफल 10.0हो जाता है क्योंकि NUMERIC(38, 1)10 38 के परिणाम को धारण करने के लिए पर्याप्त नहीं होने के लिए डाली जाती है । ऐसा इसलिए है क्योंकि 10 38 दशमलव से पहले 39 अंक लेने के लिए फैलता है, जबकि NUMERIC(38, 1)37 अंकों को दशमलव से पहले जमा कर सकता है। इसलिए, अधिकतम मूल्य NUMERIC(38, 1)10 37 - 0.1 हो सकता है।

इस समझ के साथ सशस्त्र मैं एक और अतिप्रवाह विफलता को निम्न प्रकार से नियंत्रित कर सकता हूं।

SELECT POWER(1000000000, 3);    -- one billion

एक अरब (पहले उदाहरण से एक ट्रिलियन के विपरीत, जो डाली जाती है NUMERIC(38, 0)) सिर्फ एक में फिट होने के लिए काफी छोटा है INT। तीसरी शक्ति के लिए उठाया गया एक अरब, हालांकि, INTअतिप्रवाह त्रुटि के लिए बहुत बड़ा है ।

कई अन्य कार्य समान व्यवहार प्रदर्शित करते हैं, जहां उनका आउटपुट प्रकार उनके इनपुट पर निर्भर होता है:

निष्कर्ष

इस विशेष मामले में, समाधान का उपयोग करना है SELECT POWER(1e1, precision)...। यह उन सभी संभावित पूर्वावस्थाओं के लिए काम करेगा , जो 1e1डाली जाती हैं FLOAT, जो बड़ी संख्या में हास्यास्पद हो सकती हैं ।

चूंकि ये कार्य इतने सामान्य हैं, यह समझना महत्वपूर्ण है कि आपके परिणाम गोल हो सकते हैं या उनके व्यवहार के कारण अतिप्रवाह त्रुटियों का कारण हो सकता है। यदि आप अपने आउटपुट के लिए किसी विशिष्ट डेटा प्रकार की अपेक्षा या भरोसा करते हैं, तो आवश्यक रूप से संबंधित इनपुट को स्पष्ट रूप से डालें।

तो बच्चों, अब जब आप यह जानते हैं, तो आप आगे बढ़ सकते हैं और समृद्ध हो सकते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.