2009-10-30 13 views
53

"नाम सेट" ओ रेली से "उच्च प्रदर्शन MySQL" पढ़ने मैं निम्नलिखितका उपयोग

एक अन्य आम कचरा क्वेरी पर ठोकर खाई गए नाम UTF8 है, जो करने के लिए गलत तरीके से सेट कर दिया जाता है में करना है या नहीं वैसे भी काम करें (यह क्लाइंट लाइब्रेरी के चरित्र सेट को नहीं बदलता है; यह केवल सर्वर को प्रभावित करता है)।

मैं थोड़ा उलझन में हूं, क्योंकि मैं प्रत्येक स्क्रिप्ट के शीर्ष पर "सेट नाम utf8" डालता था ताकि डीबी को पता चल सके कि मेरे प्रश्न utf8 एन्कोड किए गए हैं।

क्या कोई भी उपरोक्त उद्धरण पर टिप्पणी कर सकता है, या इसे अधिक औपचारिक रूप से रखने के लिए, आपके डेटाबेस वर्कफ़्लो को यूनिकोड-जागरूक होने के लिए आपके सुझाव/सर्वोत्तम अभ्यास क्या हैं।

यदि यह प्रासंगिक है तो मेरी लक्षित भाषाएं PHP और पायथन हैं।

+2

आपने किस तकनीक को कार्यान्वित करने का अंत किया? –

उत्तर

28

mysql_set_charset() के साथ बनाई गई एक विकल्प होगा एक कनेक्शन है - लेकिन एक विकल्प ext/mysql तक सीमित है। ext/mysqli के लिए यह mysqli_set_charset है और PDO::mysql के लिए आपको एक कनेक्शन पैरामीटर निर्दिष्ट करने की आवश्यकता है।

इस फ़ंक्शन का उपयोग करने के रूप में एक MySQL API कॉल में परिणाम होता है, इसे क्वेरी जारी करने से बहुत तेज माना जाना चाहिए।

प्रदर्शन के संबंध में आपकी स्क्रिप्ट और MySQL सर्वर के बीच एक यूटीएफ -8-आधारित संचार सुनिश्चित करने का सबसे तेज़ तरीका MySQL सर्वर को सही तरीके से स्थापित कर रहा है। SET NAMES x के रूप में आंतरिक रूप से भी कार्यान्वित SET collation_connection = <<default_collation_of_character_set_x>> आप भी अपने my.ini/cnf में स्थिर these server variables सेट कर सकते हैं equivalent

जबकि SET character_set_connection = x
SET character_set_client = x; 
SET character_set_results = x; 
SET character_set_connection = x; 

है।

कृपया एक ही MySQL सर्वर इंस्टेंस पर चल रहे अन्य अनुप्रयोगों के साथ संभावित समस्याओं से अवगत रहें और कुछ अन्य चरित्र सेट की आवश्यकता है। क्योंकि यह तो हर जगह है

+3

PHP 5.0.5 के रूप में, mysqli में एक विधि है: http://php.net/mysqli_set_charset – xofer

+0

मैंने 'mysql_set_charset()' का उल्लेख किया - यह एक पुराना 'ext/mysql' में शामिल एक फ़ंक्शन है। जैसा ऊपर बताया गया है, न तो 'पीडीओ' और न ही 'ext/mysqli' इस ऑपरेशन के लिए सीधे कोई समर्थन प्रदान करता है। –

+1

लगता है कि मैंने जो लिंक पोस्ट किया है वह विश्वसनीय नहीं है। यहां एक बेहतर है: http://php.net/manual/en/mysqli.set-charset.php यह सुनिश्चित नहीं है कि आपका मतलब है कि mysqli इस ऑपरेशन का समर्थन नहीं करता है। – xofer

9

पाई के बारे में निश्चित नहीं है, लेकिन php में mysql_set_charset है, जो कहता है कि एसईटी नामों को निष्पादित करने के लिए यह "mysql_query() का उपयोग करके वर्णमाला [और] को बदलने का पसंदीदा तरीका है।" नोट, कि यह फ़ंक्शन MySQL 5.0.7 के लिए पेश किया गया था, इसलिए यह पिछले संस्करणों के साथ काम नहीं करेगा।

mysql_set_charset('utf8', $link); 

कहाँ $ लिंक mysql_connect

21

TLDR

// The key is the "charset=utf8" part. 
$dsn = 'mysql:host=localhost;dbname=testdb;charset=utf8'; 
$dbh = new PDO($dsn, 'user', 'pass'); 

इस उत्तर php के पीडीओ पुस्तकालय पर जोर देने के है।

एक संक्षिप्त अनुस्मारक - mysql क्लाइंट-सर्वर आर्किटेक्चर है। यह महत्वपूर्ण है क्योंकि न केवल MySQL सर्वर है जहां वास्तविक डेटाबेस है, लेकिन अलग-अलग mysql क्लाइंट ड्राइवर भी है, जो कि MySQL सर्वर से बात करता है (वे अलग-अलग इकाइयां हैं)। आप थोड़े से कह सकते हैं कि mysql क्लाइंट और pdo एक साथ मिश्रित हैं।

जब आप set names utf8 का उपयोग करते हैं, तो आप mysql पर मानक SQL क्वेरी जारी करते हैं।जबकि एसक्यूएल क्वेरी pdo के माध्यम से गुजरती है, और उसके बाद mysql क्लाइंट लाइब्रेरी के माध्यम से, और अंत में यह mysql सर्वर तक पहुंच जाती है, केवल mysql सर्वर पार्स और उस SQL ​​क्वेरी को व्याख्या करता है। यह महत्वपूर्ण है क्योंकि MySQL सर्वर किसी भी संदेश को पीडीओ या MySQL क्लाइंट को वापस नहीं भेजता है, यह बताता है कि चरित्र सेट और एन्कोडिंग बदल गई है, और इसलिए पीडीओ पूरी तरह से अज्ञानी है कि यह हुआ।

ऐसा करना महत्वपूर्ण नहीं है क्योंकि क्लाइंट लाइब्रेरी तारों को सही ढंग से संभाल नहीं सकती है अगर यह वर्तमान चरित्र सेट से अवगत नहीं है। अधिकांश सामान्य ऑपरेशन सही चरित्र सेट को जानने वाले क्लाइंट के बिना सही तरीके से काम करेंगे, लेकिन एक ऐसा जो स्ट्रिंग से बच नहीं रहा है, जैसे कि PDO::quote। आपको लगता है कि आपको ऐसे मैन्युअल आदिम स्ट्रिंग से बचने की चिंता करने की आवश्यकता नहीं है क्योंकि आप तैयार कथन का उपयोग करते हैं, लेकिन सच्चाई पीडीओ का विशाल बहुमत है: mysql उपयोगकर्ता अनजाने में emulated prepared statements का उपयोग करते हैं क्योंकि यह pdo के लिए डिफ़ॉल्ट सेटिंग है: mysql ड्राइवर अब बहुत लंबा समय एक नकली तैयार कथन वास्तविक मूल mysql तैयार कथन का उपयोग नहीं करता है जैसा कि mysql api द्वारा प्रदान किया गया है; इसके बजाय, php आपके सभी मानों पर PDO::quote() पर कॉल करने के बराबर है, और आपके सभी प्लेसहोल्डर्स को आपके लिए उद्धृत मूल्यों के साथ str_replacing कर रहा है।

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

pdo mysql ड्राइवर के लिए, आप specifying it in the DSN द्वारा कनेक्ट करते समय वर्ण सेट निर्दिष्ट कर सकते हैं। यदि आप ऐसा करते हैं तो क्लाइंट लाइब्रेरी और सर्वर दोनों वर्ण सेट के बारे में अवगत होंगे।

// The key is the "charset=utf8" part. 
$dsn = 'mysql:host=localhost;dbname=testdb;charset=utf8'; 
$dbh = new PDO($dsn, 'user', 'pass'); 

लेकिन अनुचित स्ट्रिंग से बचने में एकमात्र समस्या नहीं है। उदाहरण के लिए, आपको PDO::bindColumn का उपयोग करने में समस्याएं भी हो सकती हैं क्योंकि कॉलम नाम स्ट्रिंग के रूप में निर्दिष्ट होते हैं, और फिर एन्कोडिंग के मामले महत्वपूर्ण होते हैं। एक उदाहरण ütube नामक कॉलम नाम हो सकता है (umlaut को नोट करें), और आप latin से utf8 पर सेट नामों के माध्यम से स्विच करते हैं, और फिर आप $stmt->bindColumn('ütube', $var);ütube के साथ utf8 एन्कोडेड स्ट्रिंग होने की कोशिश करते हैं क्योंकि आपकी PHP फ़ाइल utf8 एन्कोडेड है। यह काम नहीं करेगा, आपको स्ट्रिंग को लैटिन 1 संस्करण के रूप में एन्कोड करने की आवश्यकता होगी ... और अब आपके पास सभी प्रकार की पागल चल रही है।

+2

आजकल (सितंबर 2014) पीडीओ डेटाबेस के साथ PHP को जोड़ने के तरीकों का सबसे नया और सबसे मजबूत तरीका है, मुझे लगता है कि यह उत्तर स्वीकार्य माना जाना चाहिए। – rogeriopradoj

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