2013-01-02 13 views
6

मेरे पास एक सहयोगी द्वारा लिखित एक SQL क्वेरी है जो अब यहां नहीं है। क्वेरी एक SSIS काम का हिस्सा के रूप में चलाता है, और इस महीने के रूप में निम्नलिखित त्रुटि के साथ विफल शुरू कर दिया है:एसक्यूएल - तिथि प्रश्न समस्या - डेटाटाइम रूपांतरण के लिए वर्चर के परिणामस्वरूप ऑफ-ऑफ-रेंज वैल्यू

The conversion of a varchar data type to a datetime data type resulted in an out-of-range value.

क्वेरी के साथ ही चयन सिर्फ एक बुनियादी है एक जहां खंड है कि एक निश्चित समय में मूल्यों के लिए लग रहा है रेंज (@startdate और @enddate के बीच तिथि सीमा)

समय सीमा निर्धारित करने के लिए कोड के नीचे है:

DECLARE  @RunDateTime datetime 
DECLARE  @RunDate datetime 
DECLARE  @StartDate datetime 
DECLARE  @EndDate datetime 
DECLARE  @Month int 
DECLARE  @Year int 
DECLARE  @strStartDate varchar(10) 

SET  @RunDateTime = GetDate() 
SET  @RunDate = cast(round(convert(real, @RunDateTime),0,1) as datetime) 

IF     DATEPART(d, @RunDate) = 16 
    BEGIN  
        SET @StartDate = DATEADD(d, -15, @RunDate) 
        SET @EndDate = @RunDate 
    END 
ELSE 
    BEGIN 
        IF  Month(@RunDate) = 1 
          SET @Month = 12 
        ELSE  
          SET @Month = Month(@RunDate) - 1 

        IF  Month(@RunDate) = 1 
          SET @Year = Year(@RunDate) - 1 
        ELSE 
          SET @Year = Year(@RunDate) 

        SET @strStartDate = CONVERT(varchar(2), @Month)+ '/16/' + CONVERT(varchar(4), @Year) 
        SET @StartDate = CONVERT(datetime, @strStartDate, 101) 
        SET @EndDate = @RunDate 
    END 

यह काम महीने में दो बार चलाता है। महीने के पहले से 15 वें महीने के आंकड़ों के लिए 16 वें स्थान पर, और 16 महीने से पिछले महीने के अंत तक डेटा के लिए अगले महीने के पहले महीने में।

मुझे जो ऑनलाइन मिल सकता है, varchar का उपयोग strStartDate के लिए संभावित अपराधी है? मैं एसक्यूएल के साथ पर्याप्त परिचित नहीं हूं कि यह जानने के लिए कि वहां क्या सामान बदल रहा है? साथ ही, क्या रन टाइम प्राप्त करने की तुलना में महीने की तारीख के अंत का निर्धारण करने का एक बेहतर तरीका है? किसी भी मदद की बहुत सराहना की जाएगी।

(पीएस, हम इस काम को SQL सर्वर 2008 आर 2 पर चलाते हैं) और मैंने डीबीए के साथ जांच की और उन्होंने कहा कि स्थानीयकरण या क्षेत्रीय सेटिंग्स के बारे में कुछ भी नहीं है जो SQL सर्वर पर बदल गया है।

+1

ऐसा लगता है कि आप पिछले महीने के 16 वें की गणना करने की कोशिश कर रहे हैं। स्ट्रिंग मैनिपुलेशन करने के बजाय, 'SET @StartDate = DATEADD (महीना, DATEDIFF (महीना,' 20010101 ', @ रनडेट),' 20001216 ')', 'हमेशा इसे ढूंढना चाहिए (दो स्ट्रिंग स्थिरांक को ठीक उसी तरह रखें) । –

+1

क्या आप वाकई कोड पोस्ट किए गए कोड के अनुभाग में हैं? लाइन कनवर्टर (डेटाटाइम, @स्ट्रस्टार्टडेट, 101) पर 101 इंगित करता है कि स्ट्रस्टार्टडेट एमएम/डीडी/वाईय प्रारूप में होना चाहिए, जो कि है, ताकि सर्वर की क्षेत्रीय सेटिंग्स पर निर्भर न हो। – sgmoore

+0

@Damien_The_Unbeliever हाँ, यह क्वेरी हमेशा एक महीने के पहले और 16 वें स्थान पर चली जाएगी। यदि यह एक महीने के 16 वें स्थान पर नहीं चलता है, तो यह पहला होना चाहिए, इसलिए हम StartDate मान को पिछले महीने के 16 वें का प्रतिनिधित्व करना चाहते हैं। (हम मूल रूप से केवल पिछले महीने के # 16 प्राप्त करना चाहते हैं यदि क्वेरी 1 पर चलती है) मैं इतना एसक्यूएल साक्षर नहीं हूं, लेकिन क्या आपके द्वारा प्रदान किया गया कोड किसी भी महीने के लिए काम करता है? या बस दिसंबर के लिए करते हैं? – Oryx

उत्तर

4

SQL सर्वर द्वारा समर्थित कई प्रारूप हैं - MSDN Books Online on CAST and CONVERT देखें। उन प्रारूपों में से अधिकांश प्रारूप निर्भर हैं आपके पास कौन सी सेटिंग्स हैं - इसलिए, ये सेटिंग्स कुछ बार काम कर सकती हैं - और कभी-कभी नहीं।

इस हल करने के लिए जिस तरह से (थोड़ा अनुकूलित) आईएसओ 8601 दिनांक स्वरूप कि एसक्यूएल सर्वर द्वारा समर्थित है का उपयोग करना है - इस प्रारूप काम करता है हमेशा - अपने एसक्यूएल सर्वर भाषा और DateFormat सेटिंग की परवाह किए बिना।

ISO-8601 format एसक्यूएल सर्वर द्वारा समर्थित है दो रूपों में आता है:

  • YYYYMMDD सिर्फ तारीखें (कुछ ही समय भाग) के लिए; यहां ध्यान दें: कोई डैश नहीं!, यह बहुत महत्वपूर्ण है! YYYY-MM-DD आपके SQL सर्वर में डेटफॉर्मेट सेटिंग्स से स्वतंत्र नहीं है और सभी परिस्थितियों में काम करेगा!

या:

  • दिनांक और समय के लिए YYYY-MM-DDTHH:MM:SS - यहाँ ध्यान दें: इस प्रारूप डैश है (लेकिन वे छोड़ा जा सकता है), और एक निश्चित T दिनांक और समय के बीच परिसीमक के रूप में आपके DATETIME का हिस्सा।

यह SQL Server 2000 और नए के लिए मान्य है।

आप एसक्यूएल सर्वर 2008 या नए और DATE डेटाप्रकार का उपयोग करते हैं (केवल DATE - नहींDATETIME), तो आप वास्तव में भी YYYY-MM-DD प्रारूप भी किसी भी सेटिंग के साथ अपने एसक्यूएल सर्वर में उपयोग कर सकते हैं और उस काम करेंगे, ।

इसके अलावा: SQL सर्वर 2008 के साथ, DATETIME2 (DATETIME के बजाय) का उपयोग करने की अनुशंसा की जाती है, यदि कभी भी संभव हो। DATETIME2 तारों का विश्लेषण करना त्रुटि और/या विभिन्न प्रारूपों (जैसे यूएस एएम/पीएम स्वरूपण इत्यादि) के लिए बहुत अधिक क्षमाशील है।

मुझसे मत पूछें कि यह पूरा विषय इतना मुश्किल क्यों है और कुछ हद तक भ्रमित है - यही वही तरीका है। लेकिन YYYYMMDD प्रारूप के साथ, आपको SQL सर्वर के किसी भी संस्करण और आपके SQL सर्वर में किसी भी भाषा और दिनांक स्वरूप सेटिंग के लिए ठीक होना चाहिए।

+0

इस तरह के एक पूर्ण जवाब के लिए धन्यवाद। मैं लिंक के माध्यम से पढ़ने पर काम कर रहा हूं, लेकिन मुझे लगता है कि मैं पोस्ट किए गए एसक्यूएल को संशोधित करने के व्यावहारिक पक्ष के बारे में इतना निश्चित नहीं हूं। क्या मैं बस strStartDateTime पैरामीटर को डेटाटाइम 2 में बदलता हूं? यदि हां, तो क्या मुझे महीने के 16 वें को खोजने के लिए तर्क को दोबारा करना होगा क्योंकि ऐसा लगता है कि उस पैरामीटर पर वर्चर होने पर निर्भर है? क्षमा करें अगर ये गूंगा हैं – Oryx

+1

@Oryx: यदि आपको 'DATETIME' में पार्स करने के लिए एक स्ट्रिंग बनाने की आवश्यकता है, तो मैं केवल ** सुरक्षित ** प्रारूपों में से एक का उपयोग करना सुनिश्चित करूँगा - इसलिए इसे बदलें: 'SET @strStartDate = CONVERT (वर्कर (2), @ मॉन्थ) + '/ 16 /' + कन्वर्ट (वर्चर (4), @Year) 'इस तरह से कुछ: 'YYYYMM16' और फिर कनवर्ट करें - यह एक सुरक्षित और भाषा-स्वतंत्र है प्रारूप जो हमेशा ठीक से बदल जाएगा। –

+1

@Oryx: यदि आपको तिथियों के स्ट्रिंग प्रस्तुतियों को बनाने की आवश्यकता है, तो सुरक्षित प्रारूपों का उपयोग करें, उदा। 16 जनवरी 2013 के लिए '20130116' का निर्माण - और फिर उस पर विश्लेषण करें। किसी भी भाषा और/या दिनांक प्रारूप सेटिंग के साथ, SQL सर्वर की किसी भी स्थापना पर इसे 'DATETIME' (या' DATE' या 'DATETIME2') में परिवर्तित कर दिया जाएगा - इससे कोई फर्क नहीं पड़ता। –