चरित्र सेट के साथ समस्याएं काफी आम हैं, मैं कुछ सामान्य नोट्स देने की कोशिश करता हूं।
सिद्धांत रूप में आपको चार . पर विचार करना होगा विभिन्न वर्ण सेट सेटिंग्स।
1 और 2:NLS_CHARACTERSET
और NLS_NCHAR_CHARACTERSET
उदाहरण:AL32UTF8
वे केवल defined परिभाषित हैं अपने डेटाबेस पर, आप उनसे
. के साथ पूछताछ कर सकते हैं SELECT *
FROM V$NLS_PARAMETERS
WHERE PARAMETER IN ('NLS_CHARACTERSET', 'NLS_NCHAR_CHARACTERSET');
ये सेटिंग्स परिभाषित करती हैं कि आपके डेटाबेस में कौन से वर्ण (किस प्रारूप में) संग्रहीत किए जा सकते हैं - न अधिक, न कम। यदि आपको इसे मौजूदा डेटाबेस में बदलना है तो इसके लिए कुछ प्रयास (कैरेक्टर सेट माइग्रेशन और/या यूनिकोड के लिए Oracle डेटाबेस माइग्रेशन असिस्टेंट देखें) की आवश्यकता है।
3:NLS_LANG
उदाहरण:AMERICAN_AMERICA.AL32UTF8
यह मान केवल परिभाषित किया गया है अपने ग्राहक पर। NLS_LANG का डेटाबेस में वर्णों को संग्रहीत करने की क्षमता से कोई लेना-देना नहीं है। इसका उपयोग Oracle को यह बताने के लिए किया जाता है कि आप क्लाइंट साइड पर किस वर्ण सेट का उपयोग कर रहे हैं। जब आप NLS_LANG मान सेट करते हैं (उदाहरण के लिए AL32UTF8 के लिए) तो आप केवल Oracle डेटाबेस को बताएं "मेरा क्लाइंट कैरेक्टर सेट AL32UTF8 का उपयोग करता है" - इसका मतलब यह नहीं है कि आपका क्लाइंट वास्तव में AL32UTF8 का उपयोग कर रहा है! (नीचे #4 देखें)
NLS_LANG को पर्यावरण चर NLS_LANG
. द्वारा परिभाषित किया जा सकता है या Windows रजिस्ट्री द्वारा HKLM\SOFTWARE\Wow6432Node\ORACLE\KEY_%ORACLE_HOME_NAME%\NLS_LANG
पर (32 बिट के लिए), सम्मान। HKLM\SOFTWARE\ORACLE\KEY_%ORACLE_HOME_NAME%\NLS_LANG
(64 बिट के लिए)। आपके आवेदन के आधार पर NLS_LANG निर्दिष्ट करने के अन्य तरीके भी हो सकते हैं, लेकिन आइए बुनियादी बातों पर टिके रहें। यदि NLS_LANG मान प्रदान नहीं किया जाता है तो Oracle इसे AMERICAN_AMERICA.US7ASCII
पर डिफॉल्ट कर देता है
NLS_LANG का प्रारूप NLS_LANG=language_territory.charset
है . {वर्णक्रम } NLS_LANG का हिस्सा नहीं है किसी भी सिस्टम टेबल या व्यू में दिखाया गया है। NLS_LANG परिभाषा के सभी घटक वैकल्पिक हैं, इसलिए निम्नलिखित परिभाषाएँ सभी मान्य हैं:NLS_LANG=.WE8ISO8859P1
, NLS_LANG=_GERMANY
, NLS_LANG=AMERICAN
, NLS_LANG=ITALIAN_.WE8MSWIN1252
, NLS_LANG=_BELGIUM.US7ASCII
।
जैसा कि NLS_LANG
. के {charset} भाग के ऊपर बताया गया है किसी भी सिस्टम टेबल/व्यू या किसी फ़ंक्शन पर डेटाबेस में उपलब्ध नहीं है। सच कहूं तो यह सच है, हालांकि आप इस क्वेरी को चला सकते हैं:
SELECT DISTINCT CLIENT_CHARSET
FROM V$SESSION_CONNECT_INFO
WHERE (SID, SERIAL#) = (SELECT SID, SERIAL# FROM v$SESSION WHERE AUDSID = USERENV('SESSIONID'));
इसे आपके वर्तमान NLS_LANG
. से वर्ण सेट वापस करना चाहिए सेटिंग - हालांकि मेरे अनुभव के आधार पर मान अक्सर NULL या Unknown
होता है , यानी विश्वसनीय नहीं।
अधिक उपयोगी जानकारी यहां पाएं:NLS_LANG अक्सर पूछे जाने वाले प्रश्न
ध्यान दें, कुछ प्रौद्योगिकियां NLS_LANG
. का उपयोग नहीं करती हैं , वहां सेटिंग्स का कोई प्रभाव नहीं पड़ता है, उदाहरण के लिए:
-
ODP.NET प्रबंधित ड्राइवर
NLS_LANG
नहीं है संवेदनशील। यह केवल .NET लोकेल संवेदनशील है। (.NET डेवलपर गाइड के लिए डेटा प्रदाता देखें) -
OraOLEDB (Oracle से) हमेशा UTF-16 का उपयोग करता है (OraOLEDB प्रदाता विशिष्ट सुविधाएँ देखें)
-
जावा आधारित JDBC (उदाहरण के लिए SQL डेवलपर) के पास कैरेक्टर सेट से निपटने के अपने तरीके हैं (डेटाबेस JDBC डेवलपर गाइड देखें - अधिक जानकारी के लिए वैश्वीकरण समर्थन)
4:आपके टर्मिनल का "वास्तविक" वर्ण सेट, आपका एप्लिकेशन या .sql
का एन्कोडिंग फ़ाइलें
उदाहरण:UTF-8
यदि आप विंडोज टर्मिनल (यानी SQL*plus के साथ) पर काम करते हैं तो आप chcp
कमांड के साथ कोड पेज से पूछताछ कर सकते हैं। , यूनिक्स/लिनक्स पर समतुल्य locale charmap
. है या echo $LANG
. आप यहां से सभी विंडोज कोड पेज आइडेंटिफायर की सूची प्राप्त कर सकते हैं:कोड पेज आइडेंटिफायर। नोट, UTF-8 के लिए (chcp 65001
) कुछ मुद्दे हैं, इस चर्चा को देखें।
अगर आप .sql
. के साथ काम करते हैं फ़ाइलें और एक संपादक जैसे TOAD या SQL-Developer आपको सेव विकल्पों की जाँच करनी होगी। आमतौर पर आप UTF-8
. जैसे मान चुन सकते हैं , ANSI
, ISO-8859-1
, आदि।ANSI
अर्थात Windows ANSI कोडपेज, आमतौर पर CP1252
, आप HKLM\SYSTEM\ControlSet001\Control\Nls\CodePage\ACP
पर अपनी रजिस्ट्री में जांच कर सकते हैं या यहां:राष्ट्रीय भाषा समर्थन (एनएलएस) एपीआई संदर्भ
[Microsoft ने इस संदर्भ को हटा दिया, इसे वेब-संग्रह राष्ट्रीय भाषा समर्थन (NLS) API संदर्भ के रूप में लें]
इन सभी मानों को कैसे सेट करें?
सबसे महत्वपूर्ण बिंदु NLS_LANG
. का मिलान करना है और आपके टर्मिनल का आपका "असली" चरित्र सेट, सम्मान। एप्लिकेशन या आपके .sql
. की एन्कोडिंग फ़ाइलें
कुछ सामान्य जोड़े हैं:
-
CP850 ->
WE8PC850
-
CP1252 या ANSI ("पश्चिमी" पीसी के मामले में) ->
WE8MSWIN1252
-
ISO-8859-1 ->
WE8ISO8859P1
-
ISO-8859-15 ->
WE8ISO8859P15
-
UTF-8 ->
AL32UTF8
या कुछ और पाने के लिए इस क्वेरी को चलाएँ:
SELECT VALUE AS ORACLE_CHARSET, UTL_I18N.MAP_CHARSET(VALUE) AS IANA_NAME
FROM V$NLS_VALID_VALUES
WHERE PARAMETER = 'CHARACTERSET';
कुछ प्रौद्योगिकियां आपके जीवन को आसान बनाती हैं, उदा. ODP.NET (अप्रबंधित ड्राइवर) या Oracle से ODBC ड्राइवर स्वचालित रूप से NLS_LANG
से वर्ण सेट प्राप्त करता है मान, इसलिए ऊपर से शर्त हमेशा सत्य होती है।
क्या क्लाइंट NLS_LANG मान को डेटाबेस NLS_CHARACTERSET
के बराबर सेट करना आवश्यक है मूल्य?
नहीं, जरूरी नहीं! उदाहरण के लिए, यदि आपके पास डेटाबेस . है वर्ण सेट NLS_CHARACTERSET=AL32UTF8
और क्लाइंट वर्ण सेट NLS_LANG=.ZHS32GB18030
तो यह बिना किसी समस्या के काम करेगा (बशर्ते आपका ग्राहक वास्तव में GB18030 का उपयोग करता हो), हालांकि ये वर्ण सेट पूरी तरह से अलग हैं। GB18030 आमतौर पर चीनी के लिए उपयोग किया जाने वाला वर्ण सेट है, जैसे UTF-8
यह सभी यूनिकोड वर्णों का समर्थन करता है।
यदि आपके पास है, उदाहरण के लिए NLS_CHARACTERSET=AL32UTF8
और NLS_LANG=.WE8ISO8859P1
यह भी काम करेगा (फिर से, बशर्ते आपका क्लाइंट वास्तव में ISO-8859-P1 का उपयोग करता है)। हालाँकि, डेटाबेस उन वर्णों को संग्रहीत कर सकता है जिन्हें आपका क्लाइंट प्रदर्शित करने में सक्षम नहीं है, इसके बजाय क्लाइंट एक प्लेसहोल्डर प्रदर्शित करेगा (जैसे ¿
)।
वैसे भी, यदि उपयुक्त हो तो NLS_LANG और NLS_CHARACTERSET मानों का मिलान करना फायदेमंद है। यदि वे समान हैं तो आप सुनिश्चित हो सकते हैं कि डेटाबेस में संग्रहीत कोई भी वर्ण भी प्रदर्शित किया जा सकता है और कोई भी वर्ण जो आप अपने टर्मिनल में दर्ज करते हैं या अपनी .sql फ़ाइल में लिखते हैं, डेटाबेस में संग्रहीत किया जा सकता है और प्लेसहोल्डर द्वारा प्रतिस्थापित नहीं किया जा सकता है।पी>
पूरक
कई बार आप सलाह पढ़ सकते हैं जैसे "NLS_LANG कैरेक्टर सेट आपके डेटाबेस कैरेक्टर सेट के समान होना चाहिए" (यहां SO पर भी)। यह सच नहीं है और एक लोकप्रिय मिथक है!
ये रहा सबूत:
C:\>set NLS_LANG=.AL32UTF8
C:\>sqlplus ...
SQL> SET SERVEROUTPUT ON
SQL> DECLARE
2 CharSet VARCHAR2(20);
3 BEGIN
4 SELECT VALUE INTO Charset FROM nls_database_parameters WHERE parameter = 'NLS_CHARACTERSET';
5 DBMS_OUTPUT.PUT_LINE('Database NLS_CHARACTERSET is '||Charset);
6 IF UNISTR('\20AC') = '€' THEN
7 DBMS_OUTPUT.PUT_LINE ( '"€" is equal to U+20AC' );
8 ELSE
9 DBMS_OUTPUT.PUT_LINE ( '"€" is not the same as U+20AC' );
10 END IF;
11 END;
12 /
Database NLS_CHARACTERSET is AL32UTF8
"€" is not the same as U+20AC
PL/SQL procedure successfully completed.
क्लाइंट और डेटाबेस कैरेक्टर सेट दोनों AL32UTF8
हैं , हालांकि वर्ण मेल नहीं खाते। इसका कारण है, मेरा cmd.exe
और इस प्रकार SQL*Plus भी Windows CP1252 का उपयोग करते हैं। इसलिए मुझे तदनुसार NLS_LANG सेट करना होगा:
C:\>chcp
Active code page: 1252
C:\>set NLS_LANG=.WE8MSWIN1252
C:\>sqlplus ...
SQL> SET SERVEROUTPUT ON
SQL> DECLARE
2 CharSet VARCHAR2(20);
3 BEGIN
4 SELECT VALUE INTO Charset FROM nls_database_parameters WHERE parameter = 'NLS_CHARACTERSET';
5 DBMS_OUTPUT.PUT_LINE('Database NLS_CHARACTERSET is '||Charset);
6 IF UNISTR('\20AC') = '€' THEN
7 DBMS_OUTPUT.PUT_LINE ( '"€" is equal to U+20AC' );
8 ELSE
9 DBMS_OUTPUT.PUT_LINE ( '"€" is not the same as U+20AC' );
10 END IF;
11 END;
12 /
Database NLS_CHARACTERSET is AL32UTF8
"€" is equal to U+20AC
PL/SQL procedure successfully completed.
इस उदाहरण पर भी विचार करें:
CREATE TABLE ARABIC_LANGUAGE (
LANG_CHAR VARCHAR2(20),
LANG_NCHAR NVARCHAR2(20));
INSERT INTO ARABIC_LANGUAGE VALUES ('العربية', 'العربية');
आपको NLS_LANG
. के लिए दो अलग-अलग मान सेट करने होंगे एक ही कथन के लिए - जो संभव नहीं है।