कॉलिड 6 के लिए bcp क्लाइंट से एक अमान्य स्तंभ लंबाई प्राप्त की


87

मैं सी # सर्वर से एसक्यूएल सर्वर 2005 को सीएसवी फ़ाइल डेटा को अपलोड करना चाहता हूं, लेकिन मैं नीचे त्रुटि का सामना कर रहा हूं -

कॉलिड 6 के लिए bcp क्लाइंट से एक अमान्य स्तंभ लंबाई प्राप्त की।

जब थोक प्रति डेटाबेस सर्वर को लिखते हैं

जवाबों:


69

एक्सेल में डेटा स्तंभों में से एक (कॉलम आईडी 6) में एक या अधिक सेल डेटा होते हैं जो डेटाबेस में डेटाकोलेमेंट डेटाटाइप लंबाई से अधिक होते हैं।

एक्सेल में डेटा को सत्यापित करें। डेटाबेस तालिका स्कीमा के अनुपालन में इसके प्रारूप के लिए एक्सेल में डेटा को भी सत्यापित करें।

इससे बचने के लिए, डेटाबेस तालिका में स्ट्रिंग डेटाटाइप की डेटा-लंबाई को पार करने का प्रयास करें।

उम्मीद है की यह मदद करेगा।


1
विशेष रूप से, यदि आपके पास कोई स्तंभ हैं जो 4 से छोटे VARCHAR हैं, तो अपने डेटा में NULL को 4char स्ट्रिंग "NULL" के रूप में गलत तरीके से देख लें
CrazyPyro

194

मुझे पता है कि यह पोस्ट पुरानी है, लेकिन मैं इसी मुद्दे में भाग गया और अंत में यह निर्धारित करने के लिए एक समाधान निकाला कि कौन सा कॉलम समस्या पैदा कर रहा है और इसे आवश्यकतानुसार रिपोर्ट करें। मैंने निर्धारित किया कि colidSqlException में वापस लौटना शून्य आधारित नहीं है इसलिए आपको मूल्य प्राप्त करने के लिए इसमें से 1 को घटाना होगा। उसके बाद यह _sortedColumnMappingsSqlBulkCopy उदाहरण के ArrayList के सूचकांक के रूप में उपयोग किया जाता है, SqlBulkCopy उदाहरण में जोड़े गए स्तंभ मैपिंग के सूचकांक नहीं। एक बात का ध्यान रखें कि SqlBulkCopy प्राप्त हुई पहली त्रुटि पर रुक जाएगा इसलिए यह एकमात्र मुद्दा नहीं हो सकता है लेकिन कम से कम यह पता लगाने में मदद करता है।

try
{
    bulkCopy.WriteToServer(importTable);
    sqlTran.Commit();
}    
catch (SqlException ex)
{
    if (ex.Message.Contains("Received an invalid column length from the bcp client for colid"))
    {
        string pattern = @"\d+";
        Match match = Regex.Match(ex.Message.ToString(), pattern);
        var index = Convert.ToInt32(match.Value) -1;

        FieldInfo fi = typeof(SqlBulkCopy).GetField("_sortedColumnMappings", BindingFlags.NonPublic | BindingFlags.Instance);
        var sortedColumns = fi.GetValue(bulkCopy);
        var items = (Object[])sortedColumns.GetType().GetField("_items", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(sortedColumns);

        FieldInfo itemdata = items[index].GetType().GetField("_metadata", BindingFlags.NonPublic | BindingFlags.Instance);
        var metadata = itemdata.GetValue(items[index]);

        var column = metadata.GetType().GetField("column", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).GetValue(metadata);
        var length = metadata.GetType().GetField("length", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).GetValue(metadata);
        throw new DataFormatException(String.Format("Column: {0} contains data with a length greater than: {1}", column, length));
    }

    throw;
}

4
यह बहुत अच्छी तरह से काम करता है, प्रस्तुत करने के लिए धन्यवाद।
स्टीवन

1
क्या आपको पता है कि क्या यह पंक्ति एनआर प्राप्त करना भी संभव है?
गेरहार्ड पॉवेल

2
DataFormatException एक कस्टम अपवाद है इसलिए मैं इस समस्या को अमान्य स्तंभ लंबाई के रूप में वापस रिपोर्ट कर सकता हूं। मैं अभी तक यह पता नहीं लगा पाया कि पंक्ति संख्या कैसे प्राप्त की जाए।
b_stil

1
महान समाधान, केवल एक चीज गायब है sqlTran.RollBack ();
pqsk

8
अधिकांश के लिए स्पष्ट रूप से स्पष्ट हो सकता है, लेकिन SqlException में लौटाया गया कॉलिड शून्य आधारित नहीं है " मुझे यह सूंघने में मदद की।"
पन्नाधेल

4

SQL बुलकॉपी विकल्प का उपयोग करके डेटाबेस स्ट्रिंग के लिए एक स्ट्रिंग पास करते समय मुझे इसी तरह की समस्या का सामना करना पड़ा। मैं जिस तार से गुजर रहा था वह 3 वर्णों का था जबकि गंतव्य स्तंभ की लंबाई थी varchar(20)। मैंने स्ट्रिंग में Trim()किसी स्थान (अग्रणी और अनुगामी) के कारण होने की जांच करने के लिए फ़ंक्शन का उपयोग करके DB में डालने से पहले स्ट्रिंग को ट्रिम करने की कोशिश की । स्ट्रिंग को ट्रिम करने के बाद, इसने ठीक काम किया।

तुम कोशिश कर सकते हो text.Trim()


यह बहुत अच्छा है, बहुत बहुत धन्यवाद! यह मेरे मामले में सटीक कारण था - व्हाट्सएप को पीछे छोड़ना और परिणामस्वरूप कॉलम की लंबाई पार करना।
14

यदि स्ट्रिंग अशक्त हो सकती है, तो पाठ का उपयोग करें? (।)
चार्ल्स

1

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

उदाहरण के लिए, varchar कॉलम का आकार 30 से 50 => तक बढ़ाएं

अन्य टेबल [dbo]। [तालिका का नाम] ALTER COLUMN [ColumnName] Varchar (50)


0

कोड का महान टुकड़ा, साझा करने के लिए धन्यवाद!

मैंने वास्तविक DataMemberName को एक त्रुटि पर एक ग्राहक को वापस लाने के लिए प्रतिबिंब का उपयोग करके समाप्त कर दिया (मैं WCF सेवा में बल्क सेव का उपयोग कर रहा हूं)। उम्मीद है कि कोई और व्यक्ति यह पाएगा कि मैंने इसे कैसे उपयोगी बनाया।

static string GetDataMemberName(string colName, object t) {
  foreach(PropertyInfo propertyInfo in t.GetType().GetProperties()) {
    if (propertyInfo.CanRead) {
      if (propertyInfo.Name == colName) {
        var attributes = propertyInfo.GetCustomAttributes(typeof(DataMemberAttribute), false).FirstOrDefault() as DataMemberAttribute;
        if (attributes != null && !string.IsNullOrEmpty(attributes.Name))
          return attributes.Name;
        return colName;
      }
    }
  }
  return colName;
}


इसे कैसे लागू किया जा सकता है?
अपोलो

0

मुझे यह त्रुटि संदेश हाल ही के ssis संस्करण (बनाम 2015 उद्यम, मुझे लगता है कि यह ssis 2016 है) के साथ मिला। मैं यहां टिप्पणी करूंगा क्योंकि यह पहला संदर्भ है जो आपके द्वारा इस त्रुटि संदेश को प्राप्त करने पर आता है। मुझे लगता है कि यह ज्यादातर चरित्र स्तंभों के साथ होता है जब स्रोत चरित्र आकार लक्ष्य चरित्र आकार से बड़ा होता है। मुझे यह संदेश तब मिला जब मैं एक teradata डेटाबेस से ms sql के लिए एक ado.net इनपुट का उपयोग कर रहा था। अजीब बात है क्योंकि पूर्व oledb ms sql को लिखता है कि कोई कोडिंग ओवरराइड के साथ पूरी तरह से सभी चरित्र रूपांतरण को नियंत्रित करता है। कॉलीड नंबर और एक संबंधित डेस्टिनेशन इनपुट कॉलम # आपको कभी-कभी कॉलीड संदेश के साथ मिलता है बेकार हैं। यह स्तम्भ नहीं है जब आप मैपिंग के शीर्ष से या जैसे कुछ भी गिनते हैं। यदि मैं Microsoft होता, तो मैं ' घ एक त्रुटि संदेश देने के लिए तैयार किया गया है जो ऐसा दिखता है कि यह समस्या स्तंभ पर इंगित कर रहा है जब यह नहीं है। मैंने एक शिक्षित अनुमान लगाकर समस्या को शांत किया और फिर मैपिंग के इनपुट को "इग्नोर" करने के लिए बदल दिया और फिर पुनर्मिलन करें और देखें कि क्या संदेश चला गया। मेरे मामले में और मेरे वातावरण में मैंने इसे रूट द्वारा तय किया ('आउटपुट कॉलम के लिए ms sql घोषणा के चरित्र के आकार के लिए Teradata इनपुट आईएनजी। सुनिश्चित करें कि आपके इनपुट डेटा सब कुछ आप डेटा रूपांतरण और मैपिंग के माध्यम से प्रसारित करता है।) ऐसा नहीं होने पर और मुझे अपने सभी डेटा रूपांतरण और मैपिंग को हटाना पड़ा और फिर से शुरू करना पड़ा। फिर से अजीब बात है कि OLEDB ने इसे संभाला और ADO.net ने त्रुटि को फेंक दिया और इसे काम करने के लिए यह सब हस्तक्षेप करना पड़ा। जब आपका लक्ष्य MS Sql हो तो OLEDB का उपयोग करना चाहिए। समस्या स्तंभ पर इंगित करते समय ऐसा नहीं है। मैंने एक शिक्षित अनुमान लगाकर समस्या को शांत किया और फिर मैपिंग के इनपुट को "इग्नोर" करने के लिए बदल दिया और फिर रीरन किया और देखा कि क्या संदेश चला गया है। मेरे मामले में और मेरे वातावरण में मैंने इसे रूट द्वारा तय किया ('आउटपुट कॉलम के लिए ms sql घोषणा के चरित्र के आकार के लिए Teradata इनपुट आईएनजी। सुनिश्चित करें कि आपका इनपुट रूट सभी डेटा रूपांतरणों और मैपिंग के माध्यम से प्रचार करता है। ऐसा नहीं होने पर और मुझे अपने सभी डेटा रूपांतरण और मैपिंग को हटाना पड़ा और फिर से शुरू करना पड़ा। फिर से अजीब बात है कि OLEDB ने इसे संभाला और ADO.net ने त्रुटि को फेंक दिया और इसे काम करने के लिए यह सब हस्तक्षेप करना पड़ा। जब आपका लक्ष्य MS Sql हो तो OLEDB का उपयोग करना चाहिए। समस्या स्तंभ पर इंगित करते समय ऐसा नहीं है। मैंने एक शिक्षित अनुमान लगाकर समस्या को शांत किया और फिर मैपिंग के इनपुट को "इग्नोर" करने के लिए बदल दिया और फिर पुनर्मिलन करें और देखें कि क्या संदेश चला गया। मेरे मामले में और मेरे वातावरण में मैंने इसे रूट द्वारा तय किया ('आउटपुट कॉलम के लिए ms sql घोषणा के चरित्र के आकार के लिए Teradata इनपुट आईएनजी। सुनिश्चित करें कि आपके इनपुट डेटा सब कुछ आप डेटा रूपांतरण और मैपिंग के माध्यम से प्रसारित करता है।) ऐसा नहीं होने पर और मुझे अपने सभी डेटा रूपांतरण और मैपिंग को हटाना पड़ा और फिर से शुरू करना पड़ा। फिर से अजीब बात है कि OLEDB ने इसे संभाला और ADO.net ने त्रुटि को फेंक दिया और इसे काम करने के लिए यह सब हस्तक्षेप करना पड़ा। जब आपका लक्ष्य MS Sql हो तो OLEDB का उपयोग करना चाहिए। मैंने एक शिक्षित अनुमान लगाकर समस्या को शांत किया और फिर मैपिंग के इनपुट को "इग्नोर" करने के लिए बदल दिया और फिर पुनर्मिलन करें और देखें कि क्या संदेश चला गया। मेरे मामले में और मेरे वातावरण में मैंने इसे रूट द्वारा तय किया ('आउटपुट कॉलम के लिए ms sql घोषणा के चरित्र के आकार के लिए Teradata इनपुट आईएनजी। सुनिश्चित करें कि आपके इनपुट डेटा सब कुछ आप डेटा रूपांतरण और मैपिंग के माध्यम से प्रसारित करता है।) ऐसा नहीं होने पर और मुझे अपने सभी डेटा रूपांतरण और मैपिंग को हटाना पड़ा और फिर से शुरू करना पड़ा। फिर से अजीब बात है कि OLEDB ने इसे संभाला और ADO.net ने त्रुटि को फेंक दिया और इसे काम करने के लिए यह सब हस्तक्षेप करना पड़ा। जब आपका लक्ष्य MS Sql हो तो OLEDB का उपयोग करना चाहिए। मैंने एक शिक्षित अनुमान लगाकर समस्या को शांत किया और फिर मैपिंग के इनपुट को "इग्नोर" करने के लिए बदल दिया और फिर पुनर्मिलन करें और देखें कि क्या संदेश चला गया। मेरे मामले में और मेरे वातावरण में मैंने इसे रूट द्वारा तय किया ('आउटपुट कॉलम के लिए ms sql घोषणा के चरित्र के आकार के लिए Teradata इनपुट आईएनजी। सुनिश्चित करें कि आपका इनपुट रूट सभी डेटा रूपांतरणों और मैपिंग के माध्यम से प्रचार करता है। ऐसा नहीं होने पर और मुझे अपने सभी डेटा रूपांतरण और मैपिंग को हटाना पड़ा और फिर से शुरू करना पड़ा। फिर से अजीब बात है कि OLEDB ने इसे संभाला और ADO.net ने त्रुटि को फेंक दिया और इसे काम करने के लिए यह सब हस्तक्षेप करना पड़ा। जब आपका लक्ष्य MS Sql हो तो OLEDB का उपयोग करना चाहिए। एस और मैपिंग और फिर से शुरू। फिर से मजेदार कि OLEDB ने इसे संभाला और ADO.net ने त्रुटि को फेंक दिया और इसे काम करने के लिए यह सब हस्तक्षेप करना पड़ा। सामान्य तौर पर आपको अपने लक्ष्य MS Sql के होने पर OLEDB का उपयोग करना चाहिए। एस और मैपिंग और फिर से शुरू। फिर से मजेदार कि OLEDB ने इसे संभाला और ADO.net ने त्रुटि को फेंक दिया और इसे काम करने के लिए यह सब हस्तक्षेप करना पड़ा। जब आपका लक्ष्य MS Sql हो तो सामान्य तौर पर आपको OLEDB का उपयोग करना चाहिए।


0

मैं बस इस पर ठोकर खाई और @ b_stil के स्निपेट का उपयोग करते हुए, मैं अपराधी कॉलम का पता लगाने में सक्षम था। और भविष्य की जांच पर, मुझे लगा कि मुझे कॉलम को ट्रिम करने की ज़रूरत है जैसे @Liji Chandran ने सुझाव दिया था लेकिन मैं IExcelDataReader का उपयोग कर रहा था और मैं अपने 160 कॉलमों में से प्रत्येक को मान्य और ट्रिम करने का आसान तरीका नहीं खोज सका।

तब मैं CSVReader के इस वर्ग, (मान्यकरण दाता ) वर्ग पर लड़खड़ा गया

इस वर्ग के बारे में दिलचस्प बात यह है कि यह आपको स्रोत और गंतव्य कॉलम डेटा की लंबाई, अपराधी पंक्ति और यहां तक ​​कि स्तंभ का मान देता है जो त्रुटि का कारण बन रहा है।

मैंने जो कुछ किया था, वह सभी (नवरच, वरचर, चार और नच) कॉलमों को ट्रिम कर रहा था।

मैंने अपना GetValueतरीका बदल दिया है :

 object IDataRecord.GetValue(int i)
    {
        object columnValue = reader.GetValue(i);

        if (i > -1 && i < lookup.Length)
        {
            DataRow columnDef = lookup[i];
            if
            (
                (
                    (string)columnDef["DataTypeName"] == "varchar" ||
                    (string)columnDef["DataTypeName"] == "nvarchar" ||
                    (string)columnDef["DataTypeName"] == "char" ||
                    (string)columnDef["DataTypeName"] == "nchar"
                ) &&
                (
                    columnValue != null &&
                    columnValue != DBNull.Value
                )
            )
            {
                string stringValue = columnValue.ToString().Trim();

                columnValue = stringValue;


                if (stringValue.Length > (int)columnDef["ColumnSize"])
                {
                    string message =
                        "Column value \"" + stringValue.Replace("\"", "\\\"") + "\"" +
                        " with length " + stringValue.Length.ToString("###,##0") +
                        " from source column " + (this as IDataRecord).GetName(i) +
                        " in record " + currentRecord.ToString("###,##0") +
                        " does not fit in destination column " + columnDef["ColumnName"] +
                        " with length " + ((int)columnDef["ColumnSize"]).ToString("###,##0") +
                        " in table " + tableName +
                        " in database " + databaseName +
                        " on server " + serverName + ".";

                    if (ColumnException == null)
                    {
                        throw new Exception(message);
                    }
                    else
                    {
                        ColumnExceptionEventArgs args = new ColumnExceptionEventArgs();

                        args.DataTypeName = (string)columnDef["DataTypeName"];
                        args.DataType = Type.GetType((string)columnDef["DataType"]);
                        args.Value = columnValue;
                        args.SourceIndex = i;
                        args.SourceColumn = reader.GetName(i);
                        args.DestIndex = (int)columnDef["ColumnOrdinal"];
                        args.DestColumn = (string)columnDef["ColumnName"];
                        args.ColumnSize = (int)columnDef["ColumnSize"];
                        args.RecordIndex = currentRecord;
                        args.TableName = tableName;
                        args.DatabaseName = databaseName;
                        args.ServerName = serverName;
                        args.Message = message;

                        ColumnException(args);

                        columnValue = args.Value;
                    }
                }



            }
        }

        return columnValue;
    }

आशा है कि यह किसी की मदद करता है

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