MySQL त्रुटि: एक महत्वपूर्ण लंबाई के बिना मुख्य विनिर्देश


363

मेरे पास एक प्राथमिक कुंजी के साथ एक तालिका है जो एक varchar (255) है। कुछ मामले सामने आए हैं जहां 255 वर्ण पर्याप्त नहीं हैं। मैंने फ़ील्ड को एक पाठ में बदलने की कोशिश की, लेकिन मुझे निम्न त्रुटि मिली:

BLOB/TEXT column 'message_id' used in key specification without a key length

मैं इसे कैसे ठीक करूं?

संपादित करें: मुझे यह भी इंगित करना चाहिए कि इस तालिका में कई स्तंभों के साथ एक समग्र प्राथमिक कुंजी है।


9
एक टेबल में कई प्राथमिक कुंजी नहीं हो सकती हैं। क्या आपका मतलब है कि इसकी एक समग्र प्राथमिक कुंजी है (जिसमें एक से अधिक कॉलम शामिल हैं) या इसकी कई UNIQUEकुंजियाँ हैं?
क्वासोई 16

1
मेरे मामले में किसी कारण से मेरे पास VARCHAR के बजाय एक ईमेल कॉलम के लिए एक पाठ प्रकार था।
क्रि।

अद्वितीय अक्षरांकीय के लिए VARCHAR का उपयोग करें।
JWC

जवाबों:


571

त्रुटि इसलिए होती है क्योंकि MySQL BLOB या TEXTकॉलम के केवल पहले N वर्णों को अनुक्रमित कर सकता है । त्रुटि मुख्य रूप से होता है तो वहाँ के एक क्षेत्र / स्तंभ प्रकार है जब TEXTया ब्लॉब या से संबंधित उन TEXTया BLOBजैसे प्रकार TINYBLOB, MEDIUMBLOB, LONGBLOB, TINYTEXT, MEDIUMTEXT, और LONGTEXTहै कि आप एक प्राथमिक कुंजी या सूचकांक बनाने के लिए प्रयास करें। पूर्ण BLOBया TEXTलंबाई मान के बिना, MySQL स्तंभ की विशिष्टता की गारंटी देने में असमर्थ है क्योंकि यह परिवर्तनशील और गतिशील आकार का है। इसलिए, जब एक इंडेक्स के रूप में उपयोग BLOBया TEXTटाइप किया जाता है, तो एन के मूल्य की आपूर्ति की जानी चाहिए ताकि MySQL प्रमुख लंबाई निर्धारित कर सके। हालाँकि, MySQL कुंजी लंबाई सीमा का समर्थन नहीं करता है TEXTया BLOBTEXT(88)बस काम नहीं करेगा।

त्रुटि भी पॉप-अप जब आप एक तालिका स्तंभ में कनवर्ट करने की कोशिश करेंगे non-TEXTऔर non-BLOBइस तरह के रूप टाइप VARCHARऔर ENUMमें TEXTया BLOBस्तंभ में अद्वितीय की कमी या सूचकांक के रूप में परिभाषित किया गया साथ, टाइप। ऑल्टर टेबल SQL कमांड विफल हो जाएगी।

समस्या का समाधान सूचकांक या अद्वितीय बाधा से TEXTया BLOBस्तंभ को हटाने या किसी अन्य फ़ील्ड को प्राथमिक कुंजी के रूप में सेट करना है। यदि आप ऐसा नहीं कर सकते, और स्तंभ TEXTया BLOBस्तंभ पर एक सीमा रखना चाहते हैं, तो उस VARCHARप्रकार का उपयोग करने की कोशिश करें और उस पर लंबाई की सीमा रखें। डिफ़ॉल्ट रूप से, VARCHARअधिकतम 255 वर्णों तक सीमित है और इसकी सीमा को स्पष्ट रूप से घोषणा के बाद एक ब्रैकेट के भीतर निर्दिष्ट किया जाना चाहिए, अर्थात VARCHAR(200)इसे केवल 200 वर्णों तक सीमित किया जाएगा।

कभी-कभी, भले ही आप अपनी तालिका में उपयोग नहीं करते हों TEXTया BLOBसंबंधित प्रकार का हो, त्रुटि 1170 भी दिखाई दे सकती है। यह ऐसी स्थिति में होता है जब आप VARCHARकॉलम को प्राथमिक कुंजी के रूप में निर्दिष्ट करते हैं , लेकिन गलत तरीके से इसकी लंबाई या वर्ण आकार निर्धारित करते हैं। VARCHARकेवल 256 वर्णों तक स्वीकार कर सकता है, इसलिए कुछ भी जैसे कि VARCHAR(512)MySQL को VARCHAR(512)एक SMALLTEXTडेटाटाइप में ऑटो-कन्वर्ट करने के लिए मजबूर कर देगा , जो बाद में कुंजी लंबाई पर त्रुटि 1170 के साथ विफल हो जाता है यदि स्तंभ प्राथमिक कुंजी या अद्वितीय या गैर-अद्वितीय सूचकांक के रूप में उपयोग किया जाता है। इस समस्या को हल करने के लिए, VARCHARफ़ील्ड के आकार के अनुसार 256 से कम का आंकड़ा निर्दिष्ट करें ।

संदर्भ: MySQL एरर ११ (० (४२०००): BLOB / TEXT कॉलम एक मुख्य लंबाई के बिना मुख्य विशिष्टता में प्रयुक्त


13
dev.mysql.com/doc/refman/5.0/en/char.html "VARCHAR कॉलम में मान चर-लंबाई के तार हैं। लंबाई को MySQL 5.0.3 से पहले 0 से 255 तक और 0 से 65,535 के मान के रूप में निर्दिष्ट किया जा सकता है। 5.0.3 और बाद के संस्करणों में। MySQL 5.0.3 और बाद में VARCHAR की प्रभावी अधिकतम लंबाई अधिकतम पंक्ति आकार (65,535 बाइट्स, जो सभी स्तंभों के बीच साझा की गई है) के
अधीन है

1
जहाँ आप कहते हैं "MySQL एक BLOB या TEXT कॉलम के केवल पहले N वर्णों को अनुक्रमित कर सकता है", N का मान क्या है?
jameshfisher

2
"जब आप एक BLOB या TEXT कॉलम को इंडेक्स करते हैं, तो आपको इंडेक्स के लिए एक उपसर्ग लंबाई निर्दिष्ट करनी चाहिए।" dev.mysql.com/doc/refman/5.6/en/column-indexes.html
पिंटो

86

आपको परिभाषित करना चाहिए TEXTकि आप एक स्तंभ के किस प्रमुख भाग को अनुक्रमित करना चाहते हैं।

InnoDB768प्रति इंडेक्स कुंजी पर बाइट्स की सीमा होती है और आप इससे अधिक इंडेक्स नहीं बना पाएंगे।

यह ठीक काम करेगा:

CREATE TABLE t_length (
      mydata TEXT NOT NULL,
      KEY ix_length_mydata (mydata(255)))
    ENGINE=InnoDB;

ध्यान दें कि कुंजी आकार का अधिकतम मूल्य कॉलम चारसेट पर निर्भर करता है। यह 767एकल-बाइट वर्णसेट के लिए वर्ण है जैसे LATIN1और केवल 255वर्ण के लिए UTF8( MySQLकेवल उन उपयोगों के लिए BMPजिन्हें 3प्रति वर्ण अधिकांश बाइट्स की आवश्यकता होती है )

यदि आपको अपने पूरे कॉलम की आवश्यकता है PRIMARY KEY, तो गणना SHA1या MD5हैश करें और इसे एक के रूप में उपयोग करें PRIMARY KEY


ठीक वही जो मेरे द्वारा खोजा जा रहा था। धन्यवाद!
जोनाथन हिल

आकार (255 यहाँ) वास्तव में पात्रों में है और बाइट्स में नहीं है? क्योंकि मैं सोच सकता था कि UTF-8 के लिए वर्णों का उपयोग करना वास्तव में बिना किसी अतिरिक्त लाभ के जटिल होगा।
एलेक्सिस विल्के

क्षमा करें, मैं आपके प्रश्न का पालन नहीं करता। डॉक्स से: InnoDB तालिकाओं के लिए इंडेक्स कुंजी उपसर्ग लंबाई सीमा 767 बाइट्स है जो REDUNDANTया COMPACTपंक्ति प्रारूप का उपयोग करते हैं । उदाहरण के लिए, यदि आप एक पर 255 से अधिक वर्ण का एक स्तंभ उपसर्ग सूचकांक के साथ इस सीमा तक पहुंच सकता है TEXTया VARCHARस्तंभ, एक utf8mb3 वर्ण सेट और हर किरदार के लिए 3 बाइट्स की अधिकतम संभालने। REDUNDANTऔर COMPACTइस उत्तर के दिए जाने के समय ही एकमात्र प्रारूप उपलब्ध थे।
क्वासोई

62

आप परिवर्तन तालिका अनुरोध में प्रमुख लंबाई निर्दिष्ट कर सकते हैं, जैसे कुछ:

alter table authors ADD UNIQUE(name_first(20), name_second(20));

1
यह वही था जो मुझे उसी समस्या को ठीक करने के लिए आवश्यक था । धन्यवाद!
प्रति क्वेस्ट एरॉनसन

2
आपको इस दृष्टिकोण के साथ बहुत सावधान रहना चाहिए! यह शायद सबसे आसान समाधान है, लेकिन बहुत सारी स्थितियों में सबसे अच्छा नहीं है। आपकी कुंजी दो स्तंभों से युक्त है और स्तंभ क्रम महत्वपूर्ण है।
MrD

सबसे अच्छा जवाब यहाँ।
जॉर्ज चल्हौब

यह मेरा मुद्दा हल करता है, बहुत-बहुत धन्यवाद!
डेलेयर

22

MySQL एक पूर्ण मान को अनुक्रमणित करता है BLOB, TEXTऔर लंबे VARCHARकॉलम क्योंकि उनमें मौजूद डेटा बहुत बड़ा हो सकता है, और अंतर्निहित DB इंडेक्स बड़ा होगा, जिसका अर्थ इंडेक्स से कोई लाभ नहीं है।

MySQL के लिए आवश्यक है कि आप पहले N वर्णों को अनुक्रमित करने के लिए परिभाषित करें, और चाल एक संख्या N को चुनने के लिए है जो अच्छी चयनात्मकता देने के लिए पर्याप्त है, लेकिन अंतरिक्ष को बचाने के लिए काफी कम है। उपसर्ग अनुक्रमणिका को लगभग उतना ही उपयोगी बनाने के लिए पर्याप्त होना चाहिए जितना कि यह होगा कि आप पूरे स्तंभ को अनुक्रमित करेंगे।

इससे पहले कि हम आगे बढ़ें हम कुछ महत्वपूर्ण शब्दों को परिभाषित करें। सूचकांक चयनात्मकता कुल अलग-अलग अनुक्रमित मूल्यों और पंक्तियों की कुल संख्या का अनुपात है । यहाँ परीक्षण तालिका के लिए एक उदाहरण है:

+-----+-----------+
| id  | value     |
+-----+-----------+
| 1   | abc       |
| 2   | abd       |
| 3   | adg       |
+-----+-----------+

यदि हम केवल पहले वर्ण (N = 1) को अनुक्रमित करते हैं, तो सूचकांक तालिका निम्न तालिका की तरह दिखाई देगी:

+---------------+-----------+
| indexedValue  | rows      |
+---------------+-----------+
| a             | 1,2,3     |
+---------------+-----------+

इस मामले में, सूचकांक चयनात्मकता आईएस = 1/3 = 0.33 के बराबर है।

आइए अब देखते हैं कि यदि हम अनुक्रमित वर्णों की संख्या को दो (N = 2) तक बढ़ाते हैं तो क्या होगा।

+---------------+-----------+
| indexedValue  | rows      |
+---------------+-----------+
| ab             | 1,2      |
| ad             | 3        |
+---------------+-----------+

इस परिदृश्य में IS = 2/3 = 0.66 जिसका अर्थ है कि हमने इंडेक्स चयनात्मकता में वृद्धि की है, लेकिन हमने इंडेक्स का आकार भी बढ़ाया है। ट्रिक न्यूनतम संख्या एन को खोजने के लिए है जिसके परिणामस्वरूप अधिकतम सूचकांक चयनात्मकता होगी

दो दृष्टिकोण हैं जो आप अपने डेटाबेस तालिका के लिए गणना कर सकते हैं। मैं इस डेटाबेस डंप पर प्रदर्शन करूंगा ।

मान लें कि हम तालिका कर्मचारियों में तालिका last_name को अनुक्रमणिका में जोड़ना चाहते हैं , और हम सबसे छोटी संख्या N को परिभाषित करना चाहते हैं जो सर्वोत्तम सूचकांक चयनात्मकता का उत्पादन करेगा।

पहले हमें सबसे अंतिम नामों की पहचान करें:

select count(*) as cnt, last_name 
from employees 
group by employees.last_name 
order by cnt

+-----+-------------+
| cnt | last_name   |
+-----+-------------+
| 226 | Baba        |
| 223 | Coorg       |
| 223 | Gelosh      |
| 222 | Farris      |
| 222 | Sudbeck     |
| 221 | Adachi      |
| 220 | Osgood      |
| 218 | Neiman      |
| 218 | Mandell     |
| 218 | Masada      |
| 217 | Boudaillier |
| 217 | Wendorf     |
| 216 | Pettis      |
| 216 | Solares     |
| 216 | Mahnke      |
+-----+-------------+
15 rows in set (0.64 sec)

जैसा कि आप देख सकते हैं, अंतिम नाम बाबा सबसे अधिक बार है। अब हम पांच अक्षर वाले उपसर्गों के साथ सबसे अधिक बार होने वाले last_name उपसर्गों को खोजने जा रहे हैं ।

+-----+--------+
| cnt | prefix |
+-----+--------+
| 794 | Schaa  |
| 758 | Mande  |
| 711 | Schwa  |
| 562 | Angel  |
| 561 | Gecse  |
| 555 | Delgr  |
| 550 | Berna  |
| 547 | Peter  |
| 543 | Cappe  |
| 539 | Stran  |
| 534 | Canna  |
| 485 | Georg  |
| 417 | Neima  |
| 398 | Petti  |
| 398 | Duclo  |
+-----+--------+
15 rows in set (0.55 sec)

हर उपसर्ग की बहुत अधिक घटनाएं होती हैं, जिसका अर्थ है कि हमें संख्या एन को बढ़ाना होगा जब तक कि मान लगभग पिछले उदाहरण के समान न हों।

यहाँ एन = 9 के लिए परिणाम हैं

select count(*) as cnt, left(last_name,9) as prefix 
from employees 
group by prefix 
order by cnt desc 
limit 0,15;

+-----+-----------+
| cnt | prefix    |
+-----+-----------+
| 336 | Schwartzb |
| 226 | Baba      |
| 223 | Coorg     |
| 223 | Gelosh    |
| 222 | Sudbeck   |
| 222 | Farris    |
| 221 | Adachi    |
| 220 | Osgood    |
| 218 | Mandell   |
| 218 | Neiman    |
| 218 | Masada    |
| 217 | Wendorf   |
| 217 | Boudailli |
| 216 | Cummings  |
| 216 | Pettis    |
+-----+-----------+

यहाँ एन = 10 के लिए परिणाम हैं।

+-----+------------+
| cnt | prefix     |
+-----+------------+
| 226 | Baba       |
| 223 | Coorg      |
| 223 | Gelosh     |
| 222 | Sudbeck    |
| 222 | Farris     |
| 221 | Adachi     |
| 220 | Osgood     |
| 218 | Mandell    |
| 218 | Neiman     |
| 218 | Masada     |
| 217 | Wendorf    |
| 217 | Boudaillie |
| 216 | Cummings   |
| 216 | Pettis     |
| 216 | Solares    |
+-----+------------+
15 rows in set (0.56 sec)

यह बहुत अच्छे परिणाम हैं। इसका अर्थ है कि हम last_nameकेवल 10 वर्णों के अनुक्रमण के साथ स्तंभ पर अनुक्रमणिका बना सकते हैं । तालिका में परिभाषा कॉलम last_nameके रूप में परिभाषित किया गया है VARCHAR(16), और इसका मतलब है कि हमने प्रति प्रविष्टि में 6 बाइट्स (या यदि अंतिम नाम में UTF8 वर्ण हैं) को सहेज लिया है। इस तालिका में १६३ distinct अलग-अलग मान हैं जो ६ बाइट से गुणा होता है, लगभग ९ केबी है, और कल्पना करें कि यदि हमारी तालिका में लाखों पंक्तियाँ हैं तो यह संख्या कैसे बढ़ेगी।

आप की संख्या की गणना करने के अन्य तरीकों पढ़ सकते हैं एन अपनी पोस्ट में MySQL में पहले से जुड़ा हुआ अनुक्रमित


3
इसे पर्याप्त अपडेट नहीं किया गया है। मुझे यह स्वीकार किए गए उत्तर की तुलना में समझने में बहुत आसान लगा
मोग कहते हैं कि मोनिका

10

पाठ प्रकार के स्तंभों के साथ एक तालिका में एक इंडेक्स जोड़ते समय मुझे यह त्रुटि मिली। आपको प्रत्येक पाठ प्रकार के लिए उपयोग की जाने वाली आकार राशि घोषित करने की आवश्यकता है।

कोष्ठक के भीतर आकार राशि डालें ()

यदि बहुत से बाइट्स का उपयोग किया जाता है, तो आप अनुक्रमण के लिए उपयोग की जाने वाली राशि को कम करने के लिए कोष्ठक में एक आकार की घोषणा कर सकते हैं। यह तब भी है जब आपने एक प्रकार के लिए पहले से ही आकार घोषित कर दिया था जैसे कि varchar (1000)। आपको नई तालिका बनाने की आवश्यकता नहीं है, जैसा कि अन्य लोगों ने कहा है।

सूचकांक जोड़ना

alter table test add index index_name(col1(255),col2(255));

अद्वितीय सूचकांक जोड़ना

alter table test add unique index_name(col1(255),col2(255));

सबसे सरल उत्तर मुझे विश्वास है और इसने मेरे लिए सीधे काम किया। धन्यवाद।
मैट क्रीमेंस


4

इससे निपटने का एक और उत्कृष्ट तरीका यह है कि अद्वितीय अवरोध के बिना अपना TEXT फ़ील्ड बनाएं और एक सिबलिंग VARCHAR फ़ील्ड जोड़ें जो अद्वितीय है और जिसमें TEXT फ़ील्ड का एक डाइजेस्ट (MD5, SHA1, आदि) शामिल है। संपूर्ण पाठ फ़ील्ड पर पाचन की गणना करें और संग्रहीत करें जब आप पाठ क्षेत्र को सम्मिलित करते हैं या अपडेट करते हैं तो आपके पास पूरे पाठ क्षेत्र (कुछ प्रमुख भाग के बजाय) पर एक विशिष्टता बाधा होती है जिसे जल्दी से खोजा जा सकता है।


1
आपको पूरी तरह से "रैंडम" स्ट्रिंग्स के साथ भी सावधान रहना चाहिए, जैसे कि एमडी 5 (), एसएचए 1 (), या यूयूआईडी () द्वारा निर्मित। उनके साथ आपके द्वारा उत्पन्न प्रत्येक नया मूल्य एक बड़े स्थान पर मनमाने तरीके से वितरित किया जाएगा, जो INSERT और कुछ प्रकार के चुनिंदा प्रश्नों को धीमा कर सकता है:
MrD

2
गैर-दुर्भावनापूर्ण डेटा पर MD5, SHA1 का वितरण समान होना चाहिए --- यही हैश के लिए।
जेबी

यह बहुत अच्छा होगा यदि आप कुछ उदाहरण दे सकें।
वेबकॉम

3

प्राथमिक कुंजी के रूप में लंबे मान नहीं हैं। जो आपके प्रदर्शन को नष्ट कर देगा। Mysql मैनुअल, खंड 13.6.13 'इनोबीडी प्रदर्शन ट्यूनिंग और समस्या निवारण' देखें।

इसके बजाय, प्राइमरी के रूप में एक सरोगेट int key है (auto_increment के साथ), और आपकी loong कुंजी एक UNIQUE के रूप में।


2

255 चर पर्याप्त नहीं होने पर ओवरफ्लो करने के लिए एक और varChar (255) कॉलम (डिफ़ॉल्ट रूप से खाली स्ट्रिंग शून्य के साथ) जोड़ें, और दोनों स्तंभों का उपयोग करने के लिए इस PK को बदलें। हालांकि यह एक अच्छी तरह से डिज़ाइन किए गए डेटाबेस स्कीमा की तरह नहीं है, और मैं आपको एक डेटा मॉडलर प्राप्त करने की सलाह दूंगा जो आपके पास सामान्यीकरण के लिए इसे फिर से शुरू करने की दिशा में एक दृश्य है।


2

समस्या का समाधान यह है कि आपके CREATE TABLEकथन में, उदाहरण के लिए, किसी फ़ील्ड के लिए वर्णों की लंबाई UNIQUE ( problemtextfield(300) )निर्दिष्ट करने के लिए स्तंभ बनाने के बाद आप बाधा जोड़ सकते हैं । तब क्षेत्र के पहले पात्रों को अद्वितीय होने की आवश्यकता होगी, और उसके बाद किसी भी मतभेद को अवहेलना किया जाएगा।key300TEXT300problemtextfield TEXT


1

इसके अलावा, यदि आप इस क्षेत्र में सूचकांक का उपयोग करना चाहते हैं, तो आपको MyISAM संग्रहण इंजन और FULLTEXT सूचकांक प्रकार का उपयोग करना चाहिए।


आप एक स्पष्टीकरण और प्रलेखन के लिंक को जोड़ने पर विचार कर सकते हैं।
लीजी

1

किसी ने भी अब तक इसका उल्लेख नहीं किया ... utf8mb4 के साथ जो 4-बाइट है और इमोटिकॉन्स को स्टोर भी कर सकता है (हमें कभी भी 3-बाइट utf8 का उपयोग नहीं करना चाहिए) और हम त्रुटियों से बच सकते हैं जैसे कि Incorrect string value: \xF0\x9F\x98\...हमें विशिष्ट VARCHAR (255) का उपयोग नहीं करना चाहिए , बल्कि VARCHAR ( 191) क्योंकि utf8mb4 और VARCHAR (255) में डेटा का एक ही हिस्सा ऑफ-पेज स्टोर किया जाता है और आप कॉलम VARCHAR (255) के लिए इंडेक्स नहीं बना सकते हैं, लेकिन VARCHAR (191) के लिए आप कर सकते हैं। यह इसलिए है क्योंकि ROW_FORMAT = COMPACT या ROW_FORMAT = REDUNDANT के लिए अधिकतम अनुक्रमित स्तंभ का आकार 767 बाइट्स है।

नई पंक्ति स्वरूपों के लिए ROW_FORMAT = DYNAMIC या ROW_FORMAT = COMPRESSED (जिसके लिए नए फ़ाइल स्वरूप innodb_file_format = Barracuda नहीं पुराने एंटीलोप की आवश्यकता है) अधिकतम अनुक्रमित स्तंभ आकार 3072 है। यह MySQL> = 5.6.3 के बाद से उपलब्ध है जब innodb_large_prefix = 1 (अक्षम) MySQL <= 5.7.6 और MySQL के लिए डिफ़ॉल्ट रूप से सक्षम = = 5.7.7)। तो इस मामले में हम अनुक्रमित स्तंभ के लिए utf8mb4 (या पुराने utf8 के लिए 1024) के लिए VARCHAR (768) का उपयोग कर सकते हैं। विकल्प innodb_large_prefix 5.7.7 के बाद से हटा दिया गया है क्योंकि इसका व्यवहार अंतर्निहित MySQL 8 (इस संस्करण में विकल्प को हटा दिया गया है) है।


0

आपको कॉलम प्रकार को अनुक्रमण के लिए varcharया उसके लिए बदलना होगा integer


आप एक स्पष्टीकरण और प्रलेखन के लिंक को जोड़ने पर विचार कर सकते हैं।
लीजी


-1

इस तरह का उपयोग करें

@Id
@Column(name = "userEmailId", length=100)
private String userEmailId;

आप एक स्पष्टीकरण और प्रलेखन के लिंक को जोड़ने पर विचार कर सकते हैं।
लीजी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.