PostgreSQL डेटाबेस पर LC_CTYPE का क्या प्रभाव है?


25

तो, मैं इस पर PostgreSQL के साथ कुछ डेबियन सर्वर है। ऐतिहासिक रूप से, वे सर्वर और PostgreSQL लैटिन 9 चारसेट और बैक के साथ स्थानीयकृत हैं, तब यह ठीक था। अब हमें पोलिश, ग्रीक या चीनी जैसी चीजों को संभालना है, इसलिए इसे बदलना एक बढ़ता हुआ मुद्दा बन गया है।

जब मैंने UTF8 डेटाबेस बनाने की कोशिश की, तो मुझे संदेश मिला:

त्रुटि: UTF8 एन्कोडिंग लोकेल fr_FR से मेल नहीं खाता है: चुने हुए LC_CTYPE सेटिंग में LATIN9 को एन्कोडिंग की आवश्यकता होती है।

कुछ समय के लिए मैंने अपने पुराने पाल गूगल के साथ इस विषय पर कुछ शोध किया, और मुझे पता चला कि कुछ जटिल प्रक्रियाएँ थीं जैसे कि डेबियन को अपडेट करना LANG, पोस्टग्रेसीक्यू को सही चारसेट के साथ अपडेट करना , सभी LC_सिस्टम चर और अन्य अस्पष्ट समाधानों को संपादित करना । इसलिए फिलहाल, हम इस मुद्दे को एक तरफ रख देते हैं।

हाल ही में, यह फिर से वापस आ गया, यूनानी लोग सामान चाहते हैं और लैटिन 9 नहीं चाहते हैं। और जब मैं इस मुद्दे पर फिर से विचार कर रहा था, एक सहकर्मी मेरे पास आया और कहा "नहीं, यह आसान है, देखो।"

उन्होंने कुछ भी संपादित नहीं किया, जादू के करतब नहीं किए, उन्होंने बस इस SQL ​​क्वेरी को बनाया:

CREATE DATABASE my_utf8_db
  WITH ENCODING='UTF8'
       OWNER=admin
       TEMPLATE=template0
       LC_COLLATE='C'
       LC_CTYPE='C'
       CONNECTION LIMIT=-1
       TABLESPACE=pg_default;

और यह ठीक काम किया।

मैं वास्तव में इसके बारे में नहीं जानता LC_CTYPE='C'था और मुझे आश्चर्य था कि इसका उपयोग Google और यहां तक ​​कि स्टैक ओवरफ्लो पर पहले समाधान पर नहीं था। मैंने चारों ओर देखा और मुझे केवल PostgreSQL प्रलेखन पर एक उल्लेख मिला।

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

तो यह मुझे आश्चर्यचकित कर गया, यह बहुत आसान है, बहुत सही है, नकारात्मक पक्ष क्या हैं? और मैं एक कठिन समय अभी तक एक जवाब मिल रहा है। तो मैं यहाँ पोस्ट करने आया हूँ:

tl; dr: किसी विशिष्ट स्थानीयकरण का उपयोग करने के नकारात्मक पहलू क्या हैं LC_CTYPE='C'? क्या ऐसा करना बुरा है? मुझे क्या तोड़ने की उम्मीद करनी चाहिए?

जवाबों:


25

एक विशिष्ट स्थानीयकरण पर LC_CTYPE = 'C' का उपयोग करने के नकारात्मक पहलू क्या हैं

दस्तावेज़ में लोकेल सपोर्ट में लोकेशन और SQL फीचर्स के बीच संबंध का उल्लेख किया गया है :

स्थानीय सेटिंग्स निम्नलिखित SQL सुविधाओं को प्रभावित करती हैं:

  • ORDER BY का उपयोग करके प्रश्नों में क्रमबद्ध क्रमबद्ध या पाठ डेटा पर मानक तुलना ऑपरेटर

  • ऊपरी, निचले और initcap फ़ंक्शंस

  • पैटर्न मिलान ऑपरेटर (LIKE, SIMILAR TO, और POSIX- शैली नियमित अभिव्यक्ति); स्थान दोनों केस असंवेदनशील मिलान और चरित्र-वर्ग नियमित अभिव्यक्ति द्वारा वर्णों के वर्गीकरण को प्रभावित करते हैं

  • कार्यों का the_char परिवार

  • LIKE क्लॉस के साथ अनुक्रमित का उपयोग करने की क्षमता

पहला आइटम (सॉर्ट ऑर्डर) के बारे में है LC_COLLATEऔर अन्य सभी के बारे में प्रतीत होते हैं LC_CTYPE

LC_COLLATE

LC_COLLATEस्ट्रिंग्स के बीच तुलना को प्रभावित करता है। व्यवहार में, सबसे अधिक दिखाई देने वाला प्रभाव क्रमबद्ध क्रम है। LC_COLLATE='C'(या POSIXजो एक पर्यायवाची है) का अर्थ है कि यह बाइट क्रम है जो तुलना करता है, जबकि language_REGIONप्रपत्र में एक लोकल का अर्थ है कि सांस्कृतिक नियम तुलनाओं को चलाएंगे।

एक नाम के साथ एक उदाहरण, UTF-8 डेटाबेस के अंदर से निष्पादित किया गया:

select firstname from (values ('bernard'), ('bérénice'), ('béatrice'), ('boris'))
 AS l(firstname)
order by firstname collate "fr_FR";

परिणाम:

 पहला नाम 
-----------
 बीट्राइस
 Bérénice
 बर्नार्ड
 बोरिस

béatriceपहले आता है boris, क्योंकि उच्चारण E, O से तुलना करता है जैसे कि वह गैर-उच्चारण था। यह एक सांस्कृतिक नियम है।

यह एक Cस्थान के साथ क्या होता है, से भिन्न होता है :

select firstname from (values ('bernard'), ('bérénice'), ('béatrice'), ('boris')) 
 AS l(firstname)
order by firstname collate "C";

परिणाम:

 पहला नाम 
-----------
 बर्नार्ड
 बोरिस
 बीट्राइस
 Bérénice

अब सूची के अंत में उच्चारण E वाले नाम धकेल दिए जाते हैं। éUTF-8 में बाइट प्रतिनिधित्व हेक्साडेसिमल C3 A9और इसके लिए oहै 6f। लोकेल के तहत c3इससे अधिक है ,।6fC'béatrice' > 'boris'

यह सिर्फ उच्चारण नहीं है। हाइफ़नेशन, विराम चिह्न और अजीब पात्रों जैसे अधिक जटिल नियम œ। प्रत्येक स्थानीय में अजीब सांस्कृतिक नियमों की अपेक्षा की जाती है।

अब अगर तुलना करने के लिए तार अलग-अलग भाषाओं को मिलाने के लिए होते हैं, जैसे firstnameकि दुनिया के सभी लोगों के लिए एक कॉलम होने पर , यह हो सकता है कि किसी भी विशेष लोकेल पर हावी नहीं होना चाहिए, वैसे भी, क्योंकि विभिन्न भाषाओं के लिए अलग-अलग अक्षरों को डिजाइन नहीं किया गया है। एक दूसरे के खिलाफ छांटे गए।

इस मामले Cमें एक तर्कसंगत विकल्प है, और इसका तेज़ होने का फायदा है, क्योंकि कुछ भी शुद्ध बाइट की तुलना को हरा नहीं सकता है।

LC_CTYPE

बीत रहा है LC_CTYPE'सी' के लिए सेट का तात्पर्य की तरह है कि सी कार्यों isupper(c)या tolower(c)केवल US-ASCII रेंज में पात्रों के लिए अपेक्षित परिणाम दे (जो है, यूनिकोड में कोडपॉइंट 0x7F तक)।

क्योंकि एसक्यूएल कार्यों की तरह upper(), lower()या initcap इन libc कार्यों की चोटी पर Postgres में लागू किया जाता है, वे जैसे ही वहाँ तार में गैर US-ASCII वर्ण हैं इस से प्रभावित कर रहे हैं।

उदाहरण:

test=> show lc_ctype;
  lc_ctype   
-------------
 fr_FR.UTF-8
(1 row)

-- Good result
test=> select initcap('élysée');
 initcap 
---------
 Élysée
(1 row)

-- Wrong result
-- collate "C" is the same as if the db has been created with lc_ctype='C'
test=> select initcap('élysée' collate "C");
 initcap 
---------
 éLyséE
(1 row)

के लिए Cस्थान, éएक uncategorizable चरित्र के रूप में व्यवहार किया जाता है।

इसी प्रकार गलत परिणाम भी नियमित भाव के साथ प्राप्त होते हैं:

test=> select 'élysée' ~ '^\w+$';
 ?column? 
----------
 t
(1 row)

test=> select 'élysée' COLLATE "C" ~ '^\w+$';
 ?column? 
----------
 f
(1 row)

इसलिए अगर मुझे यह सही लगता है, तो हमारे पास यूटीएफ -8 सर्वर बनाने पर भी ऑर्डर इश्यू होगा? मुझे लगता है कि सिस्टम LC_CTYPE UTF-8 पर सेट है, या UTF-8 में PostgreSQL संकलित करने से आपको बिंदु के समान तुलनात्मक परिणाम मिलेगा।
ग्रीनगोइर डी।

इस पर विस्तार करने के लिए, क्या यह संभव है कि तुलना स्थानीय रूप से सही हो, इसलिए प्रश्नों पर कोलायत को लागू करना संभव होगा?
ग्रीगोइरे डी।

हां, इनविजिअल स्ट्रिंग कंपैरिजन अपने स्वयं के कोलाटिंग नियमों को एम्बेड कर सकते हैं, जैसा कि मैं इस उत्तर में collate "C"बाद में करता हूं order by। यह निर्धारित करना कि आपके आवेदन की आवश्यकता है या नहीं। वहाँ से बाहर अधिकांश अनुप्रयोगों वास्तव में परवाह नहीं है।
डैनियल वेत्रे

1
यह भी ध्यान दें कि अलग-अलग कॉलम में एक स्पेसिफिक हो सकता है COLLATEजो डेटाबेस से अलग हो।
डैनियल वेरिटा

2
यह उत्तर वास्तव में LC_COLLATE के लिए है, LC_CTYPE के लिए नहीं। LC_CTYPE का उपयोग यह तय करने के लिए किया जाता है कि क्या कोई वर्ण एक अंक, अक्षर,
व्हाट्सएप

10

टकरावों का उपयोग करने के बारे में डैनियल के स्वीकृत जवाब के संदर्भ में, कृपया ध्यान रखें कि यदि आप एक मैक पर PostgreSQL चला रहे हैं तो ऑपरेटिंग सिस्टम स्तर पर कुछ collations के लिए अपर्याप्त सेटिंग्स के कारण आपकी पसंदीदा collation काम नहीं कर सकती है। आप इस मुद्दे के बारे में अधिक पढ़ सकते हैं:

http://www.postgresql.org/message-id/4B4E845F.80906@postnewspapers.com.au

यह एक PostgreSQL विशिष्ट मुद्दा नहीं है, विशेष रूप से, बल्कि कोलाज सेटिंग्स के लिए मैक के डिफ़ॉल्ट कॉन्फ़िगरेशन के साथ एक समस्या है। मेरा वर्तमान सिस्टम OS X El Capitan संस्करण 10.11 पर PostgreSQL 9.3 चला रहा है और इस समस्या से ग्रस्त है। मेरा सिस्टम समान क्वेरी परिणाम लौटाता है, भले ही मैं "fr_FR" या "en_US" टकराव का उपयोग करता हूं। उदाहरण के लिए:

"Fr_FR" कॉलेशन का उपयोग करना:

select firstname from (values ('bernard'), ('bérénice'), ('béatrice'), ('boris'))
AS l(firstname)
order by firstname collate "fr_FR";

results:
==============
bernard
boris
béatrice
bérénice

"En_US" कॉलेशन का उपयोग करना:

select firstname from (values ('bernard'), ('bérénice'), ('béatrice'), ('boris'))
AS l(firstname)
order by firstname collate "en_US";

results:
==============
bernard
boris
béatrice
bérénice

मेरे सिस्टम पर, समतलीकरण सेटिंग (ऑपरेटिंग सिस्टम स्तर पर), "fr_FR" और "en_US" के लिए समान हैं, जैसा कि शेल में अलग-अलग चलने से प्रदर्शित होता है:

cd /usr/share/locale
diff fr_FR.UTF-8/LC_COLLATE en_US.UTF-8/LC_COLLATE

उम्मीद है कि यह अतिरिक्त जानकारी इसे पढ़ने वाले किसी भी व्यक्ति के लिए उपयोगी है जो PostgreSQL का उपयोग मैक पर कर रहा है जो इस समस्या से ग्रस्त है।


मैं इसे आधुनिक मैक में कैसे काम कर सकता हूं। क्या आप अपने मैक में काम करने के लिए कुछ भी कर चुके हैं?
दिनेश कुमार
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.