PHP के साथ MySQL के लिए उपयोग करने के लिए सबसे अच्छा कोलाजेशन क्या है? [बन्द है]


731

मैं सोच रहा था कि क्या एक सामान्य वेबसाइट के लिए MySQL में "बेस्ट" विकल्प है जहाँ आप 100% सुनिश्चित नहीं हैं कि क्या दर्ज किया जाएगा? मैं समझता हूं कि सभी एनकोडिंग समान होनी चाहिए, जैसे कि MySQL, Apache, HTML और PHP के अंदर कुछ भी।

अतीत में मैंने "UTF-8" में PHP को आउटपुट के लिए सेट किया है, लेकिन MySQL में यह कौन सा कोलाज मैच करता है? मैं सोच रहा हूँ यह UTF-8 लोगों में से एक है, लेकिन मैं का इस्तेमाल किया है utf8_unicode_ci, utf8_general_ciऔर utf8_binइससे पहले कि।


35
साइड नोट: MySQL का "utf8" उचित UTF-8 (My जैसे 4+ बाइट यूनिकोड वर्णों के लिए कोई समर्थन नहीं है), हालांकि "utf8mb4" है। Utf8 के साथ, किसी फ़ील्ड को पहले असमर्थित यूनिकोड वर्ण के साथ सम्मिलित करने पर छोटा किया जाएगा। mathiasbynens.be/notes/mysql-utf8mb4
basic6

6
मुझे आश्चर्य है कि अगर हमें कभी भी उन सभी इमोजीस के लिए 5 बाइट्स की आवश्यकता होगी ... आह
we'lllvaro González

1
संबंधित प्रश्न: stackoverflow.com/questions/38228335/… "कौन सा MySQL टकराना PHP की स्ट्रिंग तुलना से बिल्कुल मेल खाता है?"
विलियम एंट्रीकेन

समझदार विकल्पों के अवलोकन के लिए: monolune.com/mysql-utf8-charsets-and-collations-explained
Flux

जवाबों:


617

मुख्य अंतर सटीकता की छँटाई है (जब भाषा में वर्णों की तुलना की जाती है) और प्रदर्शन। एकमात्र विशेष utf8_bin है जो द्विआधारी प्रारूप में वर्णों की तुलना करने के लिए है।

utf8_general_ciकी तुलना में कुछ तेज है utf8_unicode_ci, लेकिन कम सटीक (छंटाई के लिए)। विशिष्ट भाषा UTF8 एन्कोडिंग (जैसे utf8_swedish_ci) है कि उन्हें उन भाषाओं के लिए सुलझाने के लिए सबसे सटीक बनाने के अतिरिक्त भाषा नियम होते हैं। ज्यादातर समय मैं उपयोग करता हूं utf8_unicode_ci(मैं छोटे प्रदर्शन में सुधार के लिए सटीकता पसंद करता हूं), जब तक कि मेरे पास एक विशिष्ट भाषा पसंद करने का एक अच्छा कारण नहीं है।

आप MySQL मैनुअल पर विशिष्ट यूनिकोड चरित्र सेट पर अधिक पढ़ सकते हैं - http://dev.mysql.com/doc/refman/5.0/en/charset-unicode-sets.html


4
छोटे प्रदर्शन में सुधार? क्या तुम इसके बारे में निश्चित हो ? publib.boulder.ibm.com/infocenter/db2luw/v9r5/index.jsp?topic=/… आपके द्वारा चयनित टकराव डेटाबेस में प्रश्नों के प्रदर्शन को महत्वपूर्ण रूप से प्रभावित कर सकता है।
एडम रामाधन

62
यह DB2 नहीं MySQL के लिए है। इसके अलावा, कोई ठोस संख्या या बेंचमार्क नहीं हैं, इसलिए आप इसे लेखक की राय पर आधारित कर रहे हैं।
एरन गैल्परिन

3
ध्यान दें कि यदि आप फ़ंक्शंस का उपयोग करना चाहते हैं, तो MySQL में एक बग (सबसे वर्तमान में वितरित संस्करण) है, जहां फ़ंक्शंस हमेशा utf8_general_ci का उपयोग करके स्ट्रिंग लौटाते हैं, जिससे यदि आप अपने स्ट्रिंग्स के लिए किसी अन्य कॉलेशन का उपयोग कर रहे हैं तो समस्याएँ होती हैं - बग्स .mqql.com
El Yobo

1
विभिन्न स्थानों के साथ अपने अनुभव से मैं हमेशा उपयोग utf8_unicode_*
करूंगा

11
अपडेट: नए संस्करणों के लिए, अनुशंसा करें utf8mb4और utf8mb4_unicode_520_ci। ये आपको बाकी चीनी देते हैं, साथ ही बेहतर सुधार भी करते हैं।
रिक जेम्स

128

वास्तव में, आप शायद उपयोग करना चाहते हैं utf8_unicode_ciया utf8_general_ci

  • utf8_general_ci सभी उच्चारणों को अलग करके छाँटना और छाँटना जैसे कि यह ASCII था
  • utf8_unicode_ci यूनिकोड सॉर्ट क्रम का उपयोग करता है, इसलिए यह अधिक भाषाओं में सही ढंग से सॉर्ट करता है

हालाँकि, यदि आप केवल अंग्रेजी पाठ को संग्रहीत करने के लिए इसका उपयोग कर रहे हैं, तो ये अलग नहीं होने चाहिए।


1
मुझे आपका स्पष्टीकरण पसंद है! अच्छा था। लेकिन मुझे इस बात पर बेहतर समझ की आवश्यकता है कि यूनिकोड सॉर्ट ऑर्डर सही तरीके से छंटाई करने की तुलना में बेहतर क्यों है।
weia

14
@ अदम यह वास्तव में आपके लक्षित दर्शकों पर निर्भर करता है। छंटनी सही ढंग से स्थानीयकरण करने के लिए एक मुश्किल समस्या है। जैसे नार्वेजियन में अक्षर Æ Æ habet वर्णमाला के अंतिम 3 हैं। Utf8_general_ci के साथ, Å और converted O और A में परिवर्तित हो जाता है, जो उन्हें सॉर्ट किए जाने पर पूरी तरह से गलत स्थिति में डाल देता है (मुझे यकीन नहीं है कि Æ को कैसे संभाला जाता है, क्योंकि यह संयुक्ताक्षर है, उच्चारण चरित्र नहीं)। यह सॉर्ट ऑर्डर लगभग किसी भी भाषा में अलग है, जैसे नॉर्वेजियन और स्वीडिश में अलग-अलग ऑर्डर हैं (और थोड़े अलग अक्षरों को जो समान माना जाता है): Å sort Æ को सॉर्ट किया गया है in in actual (वास्तविक अक्षर Å Ä Ö हैं)। यूनिकोड इसे ठीक करता है।
Vegard Larsen

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

3
@ मैनटैक्स - किसी भी utf8_ कॉलेशन के साथ, डेटा को utf8 के रूप में संग्रहीत किया जाता है। टकराव सिर्फ इस बारे में है कि किन वर्णों को समान माना जाता है, और उन्हें कैसे आदेश दिया जाता है।
frymaster

2
@frymaster - सच नहीं है, अनुसार: mathiasbynens.be/notes/mysql-utf8mb4 "MySQL का utf8 केवल आपको सभी संभावित यूनिकोड कोड पॉइंट का 5.88% स्टोर करने की अनुमति देता है"
डेटा

120

इस समस्या के बारे में बहुत जागरूक रहें, जिसका उपयोग करते समय हो सकता है utf8_general_ci

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

यह समस्या बहुत ही कम शुरुआती 5.x संस्करणों में उजागर होती है - मुझे यकीन नहीं है कि यह व्यवहार बाद में बदल गया है।

मैं कोई डीबीए नहीं हूं, लेकिन इस समस्या से बचने के लिए, मैं हमेशा utf8-binकेस-असंवेदनशील के बजाय साथ जाता हूं ।

नीचे दी गई स्क्रिप्ट उदाहरण के द्वारा समस्या का वर्णन करती है।

-- first, create a sandbox to play in
CREATE DATABASE `sandbox`;
use `sandbox`;

-- next, make sure that your client connection is of the same 
-- character/collate type as the one we're going to test next:
charset utf8 collate utf8_general_ci

-- now, create the table and fill it with values
CREATE TABLE `test` (`key` VARCHAR(16), `value` VARCHAR(16) )
    CHARACTER SET utf8 COLLATE utf8_general_ci;

INSERT INTO `test` VALUES ('Key ONE', 'value'), ('Key TWO', 'valúe');

-- (verify)
SELECT * FROM `test`;

-- now, expose the problem/bug:
SELECT * FROM test WHERE `value` = 'value';

--
-- Note that we get BOTH keys here! MySQLs UTF8 collates that are 
-- case insensitive (ending with _ci) do not distinguish between 
-- both values!
--
-- collate 'utf8_bin' doesn't have this problem, as I'll show next:
--

-- first, reset the client connection charset/collate type
charset utf8 collate utf8_bin

-- next, convert the values that we've previously inserted in the table
ALTER TABLE `test` CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin;

-- now, re-check for the bug
SELECT * FROM test WHERE `value` = 'value';

--
-- Note that we get just one key now, as you'd expect.
--
-- This problem appears to be specific to utf8. Next, I'll try to 
-- do the same with the 'latin1' charset:
--

-- first, reset the client connection charset/collate type
charset latin1 collate latin1_general_ci

-- next, convert the values that we've previously inserted
-- in the table
ALTER TABLE `test` CONVERT TO CHARACTER SET latin1 COLLATE latin1_general_ci;

-- now, re-check for the bug
SELECT * FROM test WHERE `value` = 'value';

--
-- Again, only one key is returned (expected). This shows 
-- that the problem with utf8/utf8_generic_ci isn't present 
-- in latin1/latin1_general_ci
--
-- To complete the example, I'll check with the binary collate
-- of latin1 as well:

-- first, reset the client connection charset/collate type
charset latin1 collate latin1_bin

-- next, convert the values that we've previously inserted in the table
ALTER TABLE `test` CONVERT TO CHARACTER SET latin1 COLLATE latin1_bin;

-- now, re-check for the bug
SELECT * FROM test WHERE `value` = 'value';

--
-- Again, only one key is returned (expected).
--
-- Finally, I'll re-introduce the problem in the exact same 
-- way (for any sceptics out there):

-- first, reset the client connection charset/collate type
charset utf8 collate utf8_generic_ci

-- next, convert the values that we've previously inserted in the table
ALTER TABLE `test` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;

-- now, re-check for the problem/bug
SELECT * FROM test WHERE `value` = 'value';

--
-- Two keys.
--

DROP DATABASE sandbox;

36
-1: यह निश्चित रूप से संबंधित कॉलम के लिए एक अद्वितीय कुंजी लागू करके बनाया गया है। यदि दोनों मान 'value'और हैं , तो आप एक ही व्यवहार देखेंगे 'valUe'। एक टकराव की पूरी बात यह है कि यह (अन्य चीजों के बीच) के लिए नियम प्रदान करता है जब दो तारों को एक दूसरे के बराबर माना जाता है।
हैमराइट

13
ठीक यही समस्या है कि मैं इसका वर्णन करने की कोशिश कर रहा हूं - टकराव दो चीजें समान बनाता है जबकि वे वास्तव में समान होने के लिए अभिप्रेत नहीं हैं (और इस प्रकार, एक अद्वितीय बाधा बिल्कुल वही है जो आप हासिल करना चाहते हैं)।
ग्यूस

18
लेकिन आप इसे एक "समस्या" के रूप में वर्णित करते हैं और "बग" के लिए अग्रणी होते हैं जब व्यवहार वही होता है जो एक टकराव को प्राप्त करने का इरादा होता है। आपका विवरण सही है, लेकिन केवल उतना ही है जितना कि एक अनुचित टकराव का चयन करने के लिए डीबीए की ओर से एक त्रुटि है।
हेमराइट

32
बात यह है कि, जब आप दो उपयोगकर्ता नाम दर्ज करते हैं जो समतलीकरण के बराबर माने जाते हैं, तो यह अनुमति नहीं दी जाएगी कि क्या आप कोलॉम्न उपयोगकर्ता नाम को विशिष्ट होने के लिए सेट करते हैं, जिसे आपको अवश्य करना चाहिए!
हॉगवर्ट्स का छात्र

12
मैंने इस उत्तर और @ हैमराइट की टिप्पणी, दोनों को गलत ठहराया क्योंकि दोनों ने मिलकर मुझे टकराव की समझ तक पहुँचने में मदद की।
नच - मोनिका

86

utf8mb4कोलाज के साथ सेट चरित्र का उपयोग करना सबसे अच्छा है utf8mb4_unicode_ci

वर्ण सेट, utf8केवल UTF-8 कोड बिंदुओं की एक छोटी राशि का समर्थन करता है, लगभग 6% संभावित वर्ण। utf8केवल मूल बहुभाषी विमान (बीएमपी) का समर्थन करता है। वहाँ 16 अन्य विमानों। प्रत्येक विमान में 65,536 अक्षर हैं। utf8mb4सभी 17 विमानों का समर्थन करता है।

MySQL दूषित डेटा के परिणामस्वरूप 4 बाइट UTF-8 वर्णों को काट देगा।

utf8mb4वर्ण सेट 2010-03-24 पर MySQL 5.5.3 में पेश किया गया था।

नए वर्ण सेट का उपयोग करने के लिए कुछ आवश्यक परिवर्तन तुच्छ नहीं हैं:

  • आपके एप्लिकेशन डेटाबेस एडॉप्टर में परिवर्तन किए जाने की आवश्यकता हो सकती है।
  • वर्ण सेट करने, कोलाज़ बनाने और innodb_file_format को Barracuda में बदलने सहित my.cnf में परिवर्तन करने की आवश्यकता होगी
  • SQL CREATE स्टेटमेंट में शामिल करने की आवश्यकता हो सकती है: ROW_FORMAT=DYNAMIC
    • DARAMAR को VARCHAR (192) और बड़े पर अनुक्रमित के लिए आवश्यक है।

नोट: से स्विच करने Barracudaपर Antelope, MySQL सेवा को एक से अधिक बार पुनरारंभ करने की आवश्यकता हो सकती है। innodb_file_format_maxजब तक MySQL सेवा को फिर से शुरू नहीं किया गया है: तब तक नहीं बदलता है innodb_file_format = barracuda

MySQL पुराने AntelopeInnoDB फ़ाइल स्वरूप का उपयोग करता है । Barracudaगतिशील पंक्ति स्वरूपों का समर्थन करता है, जिन्हें आपको चार्ज करने के लिए स्विच करने के बाद अनुक्रमणिका और कुंजियाँ बनाने के लिए SQL त्रुटियों को नहीं मारना है:utf8mb4

  • # 1709 - सूचकांक स्तंभ का आकार बहुत बड़ा है। अधिकतम कॉलम का आकार 767 बाइट्स है।
  • # 1071 - निर्दिष्ट कुंजी बहुत लंबी थी; अधिकतम कुंजी लंबाई 767 बाइट्स है

निम्न परिदृश्य MySQL 5.6.17 पर परीक्षण किया गया है: डिफ़ॉल्ट रूप से, MySQL इस तरह कॉन्फ़िगर किया गया है:

SHOW VARIABLES;

innodb_large_prefix = OFF
innodb_file_format = Antelope

अपनी MySQL सेवा बंद करें और अपने मौजूदा my.cnf में विकल्प जोड़ें:

[client]
default-character-set= utf8mb4

[mysqld]
explicit_defaults_for_timestamp = true
innodb_large_prefix = true
innodb_file_format = barracuda
innodb_file_format_max = barracuda
innodb_file_per_table = true

# Character collation
character_set_server=utf8mb4
collation_server=utf8mb4_unicode_ci

उदाहरण SQL बनाएँ कथन:

CREATE TABLE Contacts (
 id INT AUTO_INCREMENT NOT NULL,
 ownerId INT DEFAULT NULL,
 created timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
 modified timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
 contact VARCHAR(640) NOT NULL,
 prefix VARCHAR(128) NOT NULL,
 first VARCHAR(128) NOT NULL,
 middle VARCHAR(128) NOT NULL,
 last VARCHAR(128) NOT NULL,
 suffix VARCHAR(128) NOT NULL,
 notes MEDIUMTEXT NOT NULL,
 INDEX IDX_CA367725E05EFD25 (ownerId),
 INDEX created (created),
 INDEX modified_idx (modified),
 INDEX contact_idx (contact),
 PRIMARY KEY(id)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE = InnoDB ROW_FORMAT=DYNAMIC;
  • यदि आप क्रिएट स्टेटमेंट से हटाए गए हैं, INDEX contact_idx (contact)तो आप त्रुटि # 1709 देख सकते हैं ROW_FORMAT=DYNAMIC

नोट: contactबाराकुडा का उपयोग करने की आवश्यकता को समाप्त करने पर पहले 128 अक्षरों तक सीमित करने के लिए सूचकांक को बदलनाROW_FORMAT=DYNAMIC

INDEX contact_idx (contact(128)),

यह भी ध्यान दें: जब यह कहता है कि फ़ील्ड का आकार VARCHAR(128)128 बाइट्स नहीं है। आप 128, 4 बाइट वर्ण या 128, 1 बाइट वर्ण का उपयोग कर सकते हैं।

इस INSERTकथन में 2 पंक्ति में 4 बाइट 'पू' वर्ण होना चाहिए:

INSERT INTO `Contacts` (`id`, `ownerId`, `created`, `modified`, `contact`, `prefix`, `first`, `middle`, `last`, `suffix`, `notes`) VALUES
(1, NULL, '0000-00-00 00:00:00', '2014-08-25 03:00:36', '1234567890', '12345678901234567890', '1234567890123456789012345678901234567890', '1234567890123456789012345678901234567890', '12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678', '', ''),
(2, NULL, '0000-00-00 00:00:00', '2014-08-25 03:05:57', 'poo', '12345678901234567890', '💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩', '💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩', '💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩', '', ''),
(3, NULL, '0000-00-00 00:00:00', '2014-08-25 03:05:57', 'poo', '12345678901234567890', '💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩', '💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩', '123💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩', '', '');

आप lastकॉलम द्वारा उपयोग किए जाने वाले स्थान की मात्रा देख सकते हैं :

mysql> SELECT BIT_LENGTH(`last`), CHAR_LENGTH(`last`) FROM `Contacts`;
+--------------------+---------------------+
| BIT_LENGTH(`last`) | CHAR_LENGTH(`last`) |
+--------------------+---------------------+
|               1024 |                 128 | -- All characters are ASCII
|               4096 |                 128 | -- All characters are 4 bytes
|               4024 |                 128 | -- 3 characters are ASCII, 125 are 4 bytes
+--------------------+---------------------+

अपने डेटाबेस एडॉप्टर में, आप अपने कनेक्शन के लिए चारसेट और कॉलेशन सेट करना चाहते हैं:

SET NAMES 'utf8mb4' COLLATE 'utf8mb4_unicode_ci'

PHP में, इसके लिए सेट किया जाएगा: \PDO::MYSQL_ATTR_INIT_COMMAND

संदर्भ:




6
utf8mb4_unicode_ci को 2015 में नई परियोजनाओं के लिए पूरी तरह से अनुशंसित टकराव होना चाहिए
ट्रेवर गेहमान

7
अपडेट ... utf8mb4_unicode_520_ciबेहतर है। भविष्य में, utf8mb4_unicode_800_ci(या ऐसा कुछ) होगा, जैसा कि MySQL यूनिकोड मानकों के साथ पकड़ता है।
रिक जेम्स

46

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

उदाहरण के लिए ड्यूरेट यूनिकोड के प्रलेखन से :

utf8_general_ciजर्मन और फ्रेंच दोनों के लिए भी संतोषजनक है, सिवाय इसके कि ß '' 's' के बराबर है, न कि 'ss' के लिए। यदि यह आपके आवेदन के लिए स्वीकार्य है, तो आपको इसका उपयोग करना चाहिए utf8_general_ciक्योंकि यह तेज़ है। अन्यथा, उपयोग करें utf8_unicode_ciक्योंकि यह अधिक सटीक है।

तो - यह आपके अपेक्षित उपयोगकर्ता आधार पर निर्भर करता है और आपको सही छंटाई की कितनी आवश्यकता है । एक अंग्रेजी उपयोगकर्ता आधार के लिए, utf8_general_ciअन्य भाषाओं के लिए, स्वीडिश की तरह पर्याप्त होना चाहिए, विशेष कोलाज बनाए गए हैं।


1
मैं utf8_general_ci का उपयोग कर रहा था और इसे छांटते समय कुछ सेकंड लगे और armcii_general_ci ने इसे बहुत जल्दी कर दिया। ऐसा क्यों हुआ? एक और सवाल, आपको क्या लगता है कि सोशल साइट्स द्वारा किस कॉलेशन का उपयोग किया जाता है

22

अनिवार्य रूप से, यह इस बात पर निर्भर करता है कि आप एक स्ट्रिंग के बारे में कैसे सोचते हैं।

मैं हमेशा utf8_bin का उपयोग करता हूं क्योंकि गुस द्वारा हाइलाइट की गई समस्या है। मेरी राय में, जहां तक ​​डेटाबेस का संबंध होना चाहिए, एक स्ट्रिंग अभी भी एक स्ट्रिंग है। एक स्ट्रिंग UTF-8 वर्णों की एक संख्या है। एक चरित्र में एक द्विआधारी प्रतिनिधित्व है, इसलिए इसे उस भाषा को जानने की आवश्यकता क्यों है जिसका आप उपयोग कर रहे हैं? आमतौर पर, लोग बहुभाषी साइटों के लिए गुंजाइश वाले सिस्टम के लिए डेटाबेस का निर्माण करेंगे। यह एक वर्ण सेट के रूप में UTF-8 का उपयोग करने का पूरा बिंदु है। मैं थोड़ा शुद्धवादी हूं, लेकिन मुझे लगता है कि बग आपको इंडेक्सिंग पर मिलने वाले मामूली लाभ से भारी जोखिम देता है। किसी भी भाषा से संबंधित नियमों को DBMS की तुलना में बहुत अधिक स्तर पर किया जाना चाहिए।

मेरी किताबों में "मूल्य" एक लाख वर्षों में कभी भी "वैल्यू" के बराबर नहीं होना चाहिए।

यदि मैं एक पाठ क्षेत्र को संग्रहीत करना चाहता हूं और एक असंवेदनशील खोज करना चाहता हूं, तो मैं PHP के कार्यों जैसे LOWER () और php फ़ंक्शन स्ट्रेटोलॉवर () के साथ MYSQL स्ट्रिंग फ़ंक्शन का उपयोग करूंगा।


9
यदि स्ट्रिंग्स की बाइनरी तुलना आपकी वांछित तुलना है, तो निश्चित रूप से आपको बाइनरी कॉलेशन का उपयोग करना चाहिए; लेकिन वैकल्पिक टकराव को "बग जोखिम" के रूप में खारिज करना या केवल अनुक्रमण की सुविधा के लिए होना यह बताता है कि आप एक टकराव के बिंदु को पूरी तरह से नहीं समझते हैं।
हैमराइट 9:11

13

UTF-8 पाठ्य सूचना के लिए, आपको उपयोग करना चाहिए utf8_general_ciक्योंकि ...

  • utf8_bin: स्ट्रिंग में प्रत्येक वर्ण के द्विआधारी मूल्य द्वारा तारों की तुलना करें

  • utf8_general_ci: सामान्य भाषा के नियमों का उपयोग करके और केस-असंवेदनशील तुलनाओं का उपयोग करके तार की तुलना करें

उर्फ यह डेटा को तेजी से / अधिक कुशल / अधिक उपयोगी खोज और अनुक्रमित करना चाहिए।


12

स्वीकृत उत्तर काफी निश्चित रूप से utf8_unicode_ci का उपयोग करने का सुझाव देता है, और नई परियोजनाओं के लिए यह बहुत अच्छा है, मैं अपने हाल के विपरीत अनुभव को संबंधित करना चाहता था, जब यह किसी को भी बचाता है।

क्योंकि utf8_general_ci MySQL में यूनिकोड के लिए डिफ़ॉल्ट मिलान है, तो आप utf8_unicode_ci उपयोग करना चाहते हैं तो आप एक में यह निर्दिष्ट करने के लिए होने अंत बहुत स्थानों में से।

उदाहरण के लिए, सभी क्लाइंट कनेक्शनों में न केवल एक डिफ़ॉल्ट चारसेट (मेरे लिए समझ में आता है) है, बल्कि एक डिफ़ॉल्ट कोलाजेशन भी है (यानी यूनिकोड के लिए utf8_general_ci को हमेशा टकराव डिफ़ॉल्ट होगा)।

इस प्रकार, यदि आप अपने खेतों के लिए utf8_unicode_ci का उपयोग करते हैं, तो डेटाबेस से जुड़ने वाली आपकी स्क्रिप्ट को वांछित टकराव का उल्लेख करने के लिए अद्यतन करने की आवश्यकता होगी - अन्यथा पाठ स्ट्रिंग का उपयोग करने वाले प्रश्न तब विफल हो सकते हैं जब आपका कनेक्शन डिफ़ॉल्ट टकराव का उपयोग कर रहा हो।

अपशॉट यह है कि किसी भी आकार की मौजूदा प्रणाली को यूनिकोड / utf8 में परिवर्तित करते समय, आप समाप्त हो सकते हैं क्योंकि MySQL डिफॉल्ट को हैंडल करने के तरीके के कारण utf8_general_ci का उपयोग करने के लिए मजबूर किया जा रहा है।


8

गुस द्वारा हाइलाइट किए गए मामले के लिए, मैं utf8_unicode_cs (ut संवेदनशील, सख्त मिलान, अधिकांश भाग के लिए सही क्रमबद्ध करने) के बजाय utf8_bin (सख्त मिलान, गलत क्रम) का उपयोग करके दृढ़ता से सुझाव दूंगा।

यदि फ़ील्ड को खोजने का इरादा है, तो उपयोगकर्ता के लिए मिलान के विपरीत, तो utf8_general_ci या utf8_unicode_ci का उपयोग करें। दोनों मामले-असंवेदनशील हैं, एक अकेला मैच होगा ('is' 'एस' के बराबर है, न कि 'एसएस')। भाषा के विशिष्ट संस्करण भी हैं, जैसे utf8_german_ci जहां निर्दिष्ट भाषा के लिए हार मिलान अधिक उपयुक्त है।

[संपादित करें - लगभग 6 साल बाद]

मैं अब MySQL पर "utf8" वर्ण सेट की अनुशंसा नहीं करता, और इसके बजाय "utf8mb4" वर्ण सेट की सिफारिश करता हूं। वे लगभग पूरी तरह से मेल खाते हैं, लेकिन थोड़ा (बहुत) अधिक यूनिकोड वर्णों के लिए अनुमति देते हैं।

वास्तविक रूप से, MySQL को "utf8" वर्ण सेट और संबंधित कोलाज को "utf8" विनिर्देश से मेल करने के लिए अद्यतन करना चाहिए था, लेकिन इसके बजाय, एक अलग वर्ण सेट और संबंधित टकराव उनके पहले से अधूरे "utf8" वर्ण सेट का उपयोग करने वालों के लिए भंडारण पदनाम को प्रभावित नहीं करने के लिए। ।


5
FYI करें: utf8_unicode_csमौजूद नहीं है। केवल केस-संवेदी utf8 है utf8_bin। समस्या utf8_binसुलझाना गलत है। देखें: stackoverflow.com/questions/15218077/…
कोस्टा

1
अपडेट करने के लिए धन्यवाद!
प्रोमेथियस

5

मुझे ये कॉलेशन चार्ट मददगार लगे। http://collation-charts.org/mysql60/ । मुझे यकीन नहीं है कि जो इस्तेमाल किया utf8_general_ci है।

उदाहरण के लिए यहां utf8_swiki_ci के लिए चार्ट है। यह दर्शाता है कि यह किस वर्ण की व्याख्या करता है। http://collation-charts.org/mysql60/mysql604.utf8_swedish_ci.html


चार्ट का एक अलग स्वाद: mysql.rjweb.org/utf8_collations.html
रिक जेम्स

2

अपने डेटाबेस अपलोड फ़ाइल में, किसी भी लाइन से पहले फॉलोइन लाइन जोड़ें:

SET NAMES utf8;

और आपकी समस्या का समाधान होना चाहिए।


2
एक प्रश्न पढ़ें: अतीत में मैंने "UTF-8" में PHP को आउटपुट के लिए सेट किया है, लेकिन MySQL में यह कौन सा कोलाज मैच करता है? मैं सोच रहा हूँ कि यह UTF-8 में से एक है, लेकिन मैंने पहले utf8_unicode_ci, utf8_general_ci, और utf8_bin का उपयोग किया है।
जितेश सोजित्रा

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