2016-03-03 8 views
7

हम Oracle 10g और Oracle 11g का उपयोग करते हैं।क्या एन फ़ंक्शन मौजूदा प्रश्नों के साथ समस्याएं पैदा कर सकता है?

हमारे पास .NET में लिखे गए छद्म-एसक्यूएल कोड से कुछ प्रश्नों को स्वचालित रूप से लिखने के लिए एक परत है (पायथन के लिए एसक्लाएल्मी जैसे कुछ)।

हमारे परत में एकल उद्धरण ' में किसी भी स्ट्रिंग लपेटता है और, अगर गैर एएनएसआई वर्ण हैं, यह स्वतः ही विशेष यूनिकोड बाइट (\00E0 की तरह) के रूप में लिखा पात्रों के साथ UNISTR लिखें।
INSERT INTO ... (...) SELECT ... FROM DUAL UNION ALL SELECT ... FROM DUAL ...

इस एल्गोरिथ्म प्रश्नों जहां एक ही स्ट्रिंग क्षेत्र कभी कभी 'my simple string' के रूप में पारित हो जाता है और कभी-कभी UNISTR('my string with special chars like \00E0') के रूप में लिपटे रचना कर सकते हैं:

अब हम निम्नलिखित निर्माण के साथ अनेक निवेशन करने के लिए एक विधि बनाया।

वर्णित स्थिति ORA-12704: character set mismatch का कारण बनती है।

एक समाधान INSERT ALL निर्माण का उपयोग करना है, लेकिन यह है बहुत धीमी गति से अब इस्तेमाल किया एक की तुलना में।

एक और समाधान किसी भी स्ट्रिंग के सामने N डालने के लिए हमारी परत को निर्देश देना है (UNISTR के साथ पहले से लिपटे वाले लोगों को छोड़कर)। यह सरल है।

मैं सिर्फ यह जानना चाहता हूं कि इससे मौजूदा प्रश्नों पर कोई दुष्प्रभाव हो सकता है या नहीं।

नोट: डीबी पर हमारे सभी फ़ील्ड या तो NCHAR या NVARCHAR2 हैं।


ओरेकल रेफरी: http://docs.oracle.com/cd/B19306_01/server.102/b14225/ch7progrunicode.htm

+1

यदि आप लक्षित कॉलम आकार को जानते हैं तो आप भी कलाकारों को डाला जा सकता है। या आपकी परत उचित थोक डालने तंत्र का समर्थन कर सकती है। लेकिन निश्चित रूप से 'एन' का उपयोग कर ... '' बस आपके डेटाबेस चरित्र से राष्ट्रीय चरित्र सेट पर डालने के दौरान शाब्दिक के दौरान शाब्दिक के एक अंतर्निहित रूपांतरण से बचाता है? –

+0

@AlexPoole Sincerly, मुझे आपके प्रश्न को समझ में नहीं आता है ... – Teejay

+1

प्रति कथन कितनी पंक्तियां डाली जा रही हैं? यदि 'INSERT ALL'' यूनियन ऑल 'से धीमा है, तो आप मेरे उत्तर [यहां] (http://stackoverflow.com/a/11663076/409172) में बताए गए अनुसार ओरेकल पार्सिंग समस्या में भाग ले रहे हैं। विशाल एसक्यूएल स्टेटमेंट के लंबे समय के समय से बचने के लिए 'INSERT ALL' को छोटे हिस्सों में तोड़ने के लिए पर्याप्त हो सकता है। –

उत्तर

2

मूल रूप से क्या आप है पूछ रहे हैं, वहाँ कैसे एक तार के साथ या एन समारोह के बिना संग्रहीत किया जाता है के बीच एक अंतर है।

तुम बस के लिए अपने आप पर विचार की जाँच कर सकते हैं:

SQL> create table test (val nvarchar2(20)); 

Table TEST created. 

SQL> insert into test select n'test' from dual; 

1 row inserted. 

SQL> insert into test select 'test' from dual; 

1 row inserted. 

SQL> select dump(val) from test; 
DUMP(VAL)                  
-------------------------------------------------------------------------------- 
Typ=1 Len=8: 0,116,0,101,0,115,0,116            
Typ=1 Len=8: 0,116,0,101,0,115,0,116 

आप समान इसलिए कोई पक्ष प्रभाव देख सकते हैं।

कारण यह इतना खूबसूरती से काम करता है यूनिकोड

की शान की वजह से है तुम यहाँ रुचि रखते हैं एक अच्छा वीडियो समझा यह

https://www.youtube.com/watch?v=MijmeoH9LT4

+0

स्ट्रिंग अक्षर पर एन हर जगह प्रदर्शन प्रदर्शन में कमी हो सकती है? – Teejay

+2

"क्या स्ट्रिंग अक्षर पर हर जगह एन को लागू करने में प्रदर्शन में कमी हो सकती है?" नहीं, ऐसा इसलिए नहीं हो सका क्योंकि नचर कॉलम में डाला गया कोई भी चार मान एनचर में स्पष्ट रूप से या स्पष्ट रूप से परिवर्तित हो गया है। –

+0

@ मिखाइलोव वेलेंटाइन धन्यवाद। तो, 'एन' के साथ, मैं बस एक * प्रक्रिया * स्पष्ट प्रक्रिया कर रहा हूं जो वैसे भी होता है? – Teejay

1

मुझे लगता है कि आप एक त्रुटि "ORA-12704: character set mismatch" क्योंकि मिलता है कोट्स के अंदर आपका डेटा चार के रूप में माना जाता है लेकिन आपके फ़ील्ड नचर हैं इसलिए चार अलग-अलग वर्णमाला का उपयोग करके चार को एकत्रित किया जाता है, एक NLS_CHARACTERSET का उपयोग करके, अन्य NLS_NCHAR_CHARACTERSET

आप एक UNISTR समारोह का उपयोग करते हैं, यह (किसी भी मामले में भी अक्षरों में एन्कोडेड मूल्यों धर्मान्तरित में) char से nchar करने के लिए डेटा धर्मान्तरित ओरेकल docs के रूप में कहते हैं:

"UNISTR अपने तर्क एक पाठ के रूप में लेता है शाब्दिक या अभिव्यक्ति कि चरित्र डेटा को हल करता है और इसे राष्ट्रीय वर्ण सेट में लौटाता है। "

जब आप मान परिवर्तित स्पष्ट N का उपयोग कर या TO_NCHAR आप केवल डिकोडिंग बिना NLS_NCHAR_CHARACTERSET में मान मिलता है। यदि आपके पास "\00E0" जैसे एन्कोड किए गए कुछ मान हैं तो उन्हें डीकोड नहीं किया जाएगा और उन्हें अपरिवर्तित माना जाएगा।

तो आप इस तरह के रूप में एक डालने अगर:

insert into select N'my string with special chars like \00E0', 
    UNISTR('my string with special chars like \00E0') from dual .... 

पहले डालने क्षेत्र में अपने डेटा हो जाएगा: 'my string with special chars like \00E0' नहीं 'my string with special chars like à'। यह एकमात्र साइड इफेक्ट है जिसे मैं जानता हूं। अन्य प्रश्नों को पहले से ही NLS_NCHAR_CHARACTERSET एन्कोडिंग का उपयोग करना चाहिए, इसलिए इसे स्पष्ट रूपांतरण का उपयोग करके कोई समस्या नहीं होनी चाहिए।

और वैसे, क्यों नहीं सभी मान N'my string with special chars like à' के रूप में डालें? अगर आप 'ऊपरी स्तर' सॉफ्टवेयर में अलग-अलग एन्कोडिंग का उपयोग करते हैं तो बस उन्हें यूटीएफ -16 में एन्कोड करें (मुझे लगता है कि आप यूटीएफ -16 का उपयोग nchars के लिए करते हैं)।

+0

* "मुझे लगता है कि आपको एक त्रुटि मिलती है" ओआरए -12704: कैरेक्टर सेट मिस्चैच "क्योंकि कोट्स के अंदर आपका डेटा चार के रूप में माना जाता है लेकिन आपके फ़ील्ड नचर हैं" * नहीं, मुझे त्रुटि मिलती है क्योंकि मैं गैर-यूनिकोड और यूनिकोड मिश्रण कर रहा हूं 'यूनियन ऑल' के साथ टेक्स्ट। – Teejay

+0

* "लेकिन अगर आपके पास इस" \ 00E0 "जैसे एन्कोड किए गए कुछ मान हैं, तो उन्हें डीकोड नहीं किया जाएगा और इन्हें माना जाएगा।" * विशेष वर्ण वाले स्ट्रिंग्स को हमारी परत से 'यूनिस्ट्र' के साथ स्वचालित रूप से लपेटा जाता है, अन्य नहीं होते हैं। यही कारण है कि मिश्रण लागू होता है, और यही कारण है कि मुझे अन्य तारों के लिए एन की आवश्यकता है। – Teejay

+0

* "और वैसे, क्यों न केवल सभी मानों को 'n'my स्ट्रिंग' के रूप में डालें, विशेष वर्णों के साथ '' '* * तो आप कह रहे हैं कि' UNISTR ('\ 00E0') का उपयोग करने के बीच कोई अंतर नहीं है। और 'ना'? – Teejay

-1
  • एन फ़ंक्शन का उपयोग - आपके पास पहले से ही उत्तर हैं।

यदि आपके पास डेटाबेस के वर्णमाला को बदलने का कोई मौका है, तो यह वास्तव में आपके जीवन को आसान बना देगा। मैं विशाल उत्पादन प्रणालियों पर काम कर रहा था, और इस प्रवृत्ति को पाया कि भंडारण की जगह सस्ता है, बस हर कोई AL32UTF8 पर जाता है और अंतर्राष्ट्रीयकरण की परेशानी धीरे-धीरे अतीत की दर्दनाक यादें बन जाती है।

मुझे सबसे आसान बात यह मिली है कि डेटाबेस उदाहरण के वर्णमाला के रूप में AL32UTF8 का उपयोग करना सबसे आसान बात है, और बस हर जगह varchar2 का उपयोग करें। हम बिना किसी नुकसान के बाध्य चर के रूप में जेडीबीसी के माध्यम से मानक जावा यूनिकोड तारों को पढ़ रहे हैं और लिख रहे हैं।

आपका विचार एसक्यूएल आवेषण की एक बड़ी पाठ कई कारणों के लिए अच्छी तरह से स्केल नहीं कर सकते हैं का निर्माण करने की:

  • वहाँ अधिकतम स्वीकृत एसक्यूएल बयान की एक निश्चित लंबाई है - तो यह 10000 आवेषण
  • साथ काम नहीं करेंगे
  • यह बाध्य चर का उपयोग करने की सलाह दी जाती है (और तब आपके पास n'xxx 'बनाम यूनिस्टर गड़बड़ नहीं है)
  • गतिशील रूप से एक नया SQL कथन बनाने का विचार बहुत संसाधन है। यह ओरेकल को किसी भी चीज़ के लिए किसी निष्पादन योजना को कैश करने की अनुमति नहीं देता है, और ओरेकल को प्रत्येक कॉल पर आपके लूप स्टेटमेंट को कठोर बना देगा।

जो आप प्राप्त करने की कोशिश कर रहे हैं वह एक द्रव्यमान सम्मिलित है। ओरेकल ड्राइवर के जेडीबीसी बैच मोड का प्रयोग हल्के गति पर करने के लिए करें, उदाहरण के लिए: http://viralpatel.net/blogs/batch-insert-in-java-jdbc/

ध्यान दें कि डालने की गति ट्रिगर्स (जिसे निष्पादित किया जाना है) और विदेशी कुंजी बाधाओं से भी प्रभावित होता है (जो होना चाहिए मान्य)।तो यदि आप कुछ हजारों पंक्तियों को सम्मिलित करने वाले हैं, तो ट्रिगर्स और विदेशी कुंजी बाधाओं को अक्षम करने पर विचार करें, और डालने के बाद उन्हें सक्षम करें। (आप ट्रिगर कॉल खो देंगे, लेकिन सम्मिलन के बाद बाधा सत्यापन एक प्रभाव डाल सकता है।)

रोलबैक सेगमेंट आकार पर भी विचार करें। यदि आप एक लाख रिकॉर्ड रिकॉर्ड कर रहे हैं, तो उसे एक बड़े रोलबैक सेगमेंट की आवश्यकता होगी, जो स्टोरेज मीडिया पर गंभीर स्वैपिंग का कारण बन जाएगा। यह प्रत्येक 1000 रिकॉर्ड के बाद अंगूठे का एक अच्छा नियम है।

(ओरेकल साझा ताले के बजाय वर्जनिंग का उपयोग करता है, इसलिए असामान्य परिवर्तन वाली एक तालिका लगातार पढ़ने के लिए उपलब्ध होती है। 1000 रिकॉर्ड प्रतिबद्धता दर का मतलब है प्रति सेकंड लगभग 1 प्रतिबद्ध - लेखन बफर के लाभ के लिए पर्याप्त धीमा, लेकिन पर्याप्त तेज़ नहीं एक ही टेबल को अपडेट करने के इच्छुक अन्य मनुष्यों के साथ हस्तक्षेप करें।)

+0

* "अधिकतम अनुमत SQL कथन की निश्चित लंबाई है - इसलिए यह 10000 प्रविष्टियों के साथ काम नहीं करेगा" *, बस सच नहीं है। ओरेकल ** ने लंबाई सीमा तय नहीं की है **, http://stackoverflow.com/questions/14355819/what-is-the- अधिकतम- स्टेटमेंट- लम्बाई-in-oracle देखें। बीटीडब्लू, हमारी परत स्वचालित रूप से प्री-डिफ़ाइंड आकार में क्वेरी को विभाजित करती है, इसलिए हमें ऐसी चीजों के बारे में चिंता करने की आवश्यकता नहीं है। – Teejay

+0

* "जो आप हासिल करने की कोशिश कर रहे हैं वह एक द्रव्यमान सम्मिलित है। ओरेकल ड्राइवर के जेडीबीसी बैच मोड का उपयोग करें" * मुझे पता है कि थोक सम्मिलित करने के तरीके हैं, यानी स्वरूपित टेक्स्ट फ़ाइल से शुरू करना, लेकिन यह मामला बस नहीं है । हमारी परत एसक्लसेवर और पोस्टग्रेस के लिए क्वेरी भी लिखती है। बीटीडब्लू, जावा ने कोई भी उल्लेख नहीं किया है, हम .NET के साथ काम करते हैं। – Teejay

+0

* "ट्रिगर्स और विदेशी कुंजी बाधाओं को अक्षम करने पर विचार करें" * हमारे पास हमारे कॉन्फ़िगरेशन में कोई ट्रिगर नहीं है।वैसे भी, कृपया ध्यान दें कि ट्रिगर्स अक्सर ऐसा कुछ नहीं करते हैं जो आप बिना नहीं कर सकते हैं, खासकर यदि वे डेटा संशोधन करते हैं। – Teejay

संबंधित मुद्दे

 संबंधित मुद्दे