डालने की कोशिश करते समय त्रुटि, स्ट्रिंग या बाइनरी डेटा को काट दिया जाएगा


250

मैं निम्नलिखित पंक्तियों के साथ data.bat फ़ाइल चला रहा हूँ:

Rem Tis batch file will populate tables

cd\program files\Microsoft SQL Server\MSSQL
osql -U sa -P Password -d MyBusiness -i c:\data.sql

Data.sql फ़ाइल की सामग्री है:

   insert Customers
            (CustomerID, CompanyName, Phone)
             Values('101','Southwinds','19126602729')

रिकॉर्ड जोड़ने के लिए 8 अधिक समान लाइनें हैं।

जब मैं के साथ इस चलाने start> run> cmd> c:\data.bat, मैं इस त्रुटि संदेश मिलता है:

1>2>3>4>5>....<1 row affected>
Msg 8152, Level 16, State 4, Server SP1001, Line 1
string or binary data would be truncated.

<1 row affected>

<1 row affected>

<1 row affected>

<1 row affected>

<1 row affected>

<1 row affected>

इसके अलावा, मैं स्पष्ट रूप से एक नौसिखिया हूं, लेकिन मैं क्या करता हूं Level #, और क्या state #मतलब है, और मैं ऊपर वाले जैसे त्रुटि संदेश कैसे देखता हूं: 15-152?

जवाबों:


609

से @ gmmastros के जवाब

जब भी मैसेज देखे…।

स्ट्रिंग या बाइनरी डेटा छोटा किया जाएगा

अपने बारे में सोचें ... मेरे डेटा को रखने के लिए क्षेत्र इतना बड़ा नहीं है।

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


16
यह भी ध्यान दें कि प्रभावित क्षेत्र एक ट्रिगर में हो सकते हैं। उम्मीद है कि अगली बार ऐसा होने पर मुझे याद होगा ...
केविन पोप

14
क्या डिबग में देखने का कोई तरीका है कि किस क्षेत्र को छोटा किया जाएगा?
DailyFrankPeter

यह त्रुटि है क्योंकि आपका कॉलम आपके द्वारा निर्धारित लंबाई के बाद डेटा नहीं रख सकता है। उदाहरण के लिए, Firstname nvarchar(5) यदि आप 5 से अधिक अक्षर सम्मिलित करते हैं तो आपको त्रुटि मिलेगी
प्रकाश

26

मेरे पास यह समस्या थी हालांकि डेटा लंबाई फ़ील्ड की लंबाई से कम थी। यह पता चला कि समस्या एक अन्य लॉग टेबल (ऑडिट ट्रेल के लिए) थी, जो मुख्य टेबल पर ट्रिगर द्वारा भरी गई थी, जहां कॉलम का आकार भी बदलना होगा।


1
धन्यवाद। खान इसलिए था क्योंकि तालिका में sql स्तंभ varchar (100) है। यह किसी अन्य तालिका में भी सम्मिलित होता है, जिसमें, कॉलम varchar (50) है।
हनीन हेट हेट औंग

1
मेरे मामले में भी यही समस्या थी। ट्रिगर ऑपरेशन अपराधी था।
ऑटोपायलट

19

किसी एक INSERTकथन में आप बहुत लंबे स्ट्रिंग को स्ट्रिंग ( varcharया nvarchar) कॉलम में सम्मिलित करने का प्रयास कर रहे हैं ।

यदि यह स्पष्ट नहीं है INSERTकि स्क्रिप्ट पर नज़र रखने वाला अपराधी है, तो आप त्रुटि संदेश से पहले<1 row affected> होने वाली लाइनों की गणना कर सकते हैं । प्राप्त नंबर प्लस एक आपको स्टेटमेंट नंबर देता है। आपके मामले में यह त्रुटि उत्पन्न करने वाला दूसरा INSERT प्रतीत होता है।


2
मुझे एक ही मुद्दा मिल रहा है, कैसे पता लगाएं कि किस कॉलम में त्रुटि हो रही है?
कोटिया माटोस

@ AndréBastos: शायद आप इसे एक प्रश्न के रूप में प्रस्तुत कर सकते हैं (जब तक कि कोई और पहले से ही ऐसा नहीं कर सकता है, उस स्थिति में इसके लिए तैयार उत्तर कहीं हो सकता है)।
एंड्री एम

11

आपका कुछ डेटा आपके डेटाबेस कॉलम (छोटे) में फिट नहीं हो सकता है। जो गलत है उसे ढूंढना आसान नहीं है। यदि आप C # और Linq2Sql का उपयोग करते हैं, तो आप उस फ़ील्ड को सूचीबद्ध कर सकते हैं जिसे काट दिया जाएगा:

पहले सहायक वर्ग बनाएँ:

public class SqlTruncationExceptionWithDetails : ArgumentOutOfRangeException
{
    public SqlTruncationExceptionWithDetails(System.Data.SqlClient.SqlException inner, DataContext context)
        : base(inner.Message + " " + GetSqlTruncationExceptionWithDetailsString(context))
    {
    }

    /// <summary>
    /// PArt of code from following link
    /// http://stackoverflow.com/questions/3666954/string-or-binary-data-would-be-truncated-linq-exception-cant-find-which-fiel
    /// </summary>
    /// <param name="context"></param>
    /// <returns></returns>
    static string GetSqlTruncationExceptionWithDetailsString(DataContext context)
    {
        StringBuilder sb = new StringBuilder();

        foreach (object update in context.GetChangeSet().Updates)
        {
            FindLongStrings(update, sb);
        }

        foreach (object insert in context.GetChangeSet().Inserts)
        {
            FindLongStrings(insert, sb);
        }
        return sb.ToString();
    }

    public static void FindLongStrings(object testObject, StringBuilder sb)
    {
        foreach (var propInfo in testObject.GetType().GetProperties())
        {
            foreach (System.Data.Linq.Mapping.ColumnAttribute attribute in propInfo.GetCustomAttributes(typeof(System.Data.Linq.Mapping.ColumnAttribute), true))
            {
                if (attribute.DbType.ToLower().Contains("varchar"))
                {
                    string dbType = attribute.DbType.ToLower();
                    int numberStartIndex = dbType.IndexOf("varchar(") + 8;
                    int numberEndIndex = dbType.IndexOf(")", numberStartIndex);
                    string lengthString = dbType.Substring(numberStartIndex, (numberEndIndex - numberStartIndex));
                    int maxLength = 0;
                    int.TryParse(lengthString, out maxLength);

                    string currentValue = (string)propInfo.GetValue(testObject, null);

                    if (!string.IsNullOrEmpty(currentValue) && maxLength != 0 && currentValue.Length > maxLength)
                    {
                        //string is too long
                        sb.AppendLine(testObject.GetType().Name + "." + propInfo.Name + " " + currentValue + " Max: " + maxLength);
                    }

                }
            }
        }
    }
}

फिर SubmitChanges के लिए आवरण तैयार करें:

public static class DataContextExtensions
{
    public static void SubmitChangesWithDetailException(this DataContext dataContext)
    {
        //http://stackoverflow.com/questions/3666954/string-or-binary-data-would-be-truncated-linq-exception-cant-find-which-fiel
        try
        {
            //this can failed on data truncation
            dataContext.SubmitChanges();
        }       
        catch (SqlException sqlException) //when (sqlException.Message == "String or binary data would be truncated.")
        {

            if (sqlException.Message == "String or binary data would be truncated.") //only for EN windows - if you are running different window language, invoke the sqlException.getMessage on thread with EN culture
                throw new SqlTruncationExceptionWithDetails(sqlException, dataContext);
            else
                throw;
        }
    }
}

वैश्विक अपवाद हैंडलर तैयार करें और ट्रंकेशन विवरण लॉग करें:

protected void Application_Error(object sender, EventArgs e)
{
    Exception ex = Server.GetLastError();
    string message = ex.Message;
    //TODO - log to file
}

अंत में कोड का उपयोग करें:

Datamodel.SubmitChangesWithDetailException();

9

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

लेकिन यह जानना बहुत जरूरी है कि इसके संभावित कारण क्या हैं।

मेरे मामले में मैं इस तरह से एक क्षेत्र के साथ तालिका बना रहा था:

Select '' as  Period, * From Transactions Into #NewTable

इसलिए "पीरियड" के क्षेत्र में जीरो की लंबाई थी और इससे इंसर्ट ऑपरेशन विफल हो गए। मैंने इसे "XXXXXX" में बदल दिया, जो आने वाले डेटा की लंबाई है और यह अब ठीक से काम करता है (क्योंकि फ़ील्ड में अब 6 का लेंटग था)।

मुझे आशा है कि यह किसी को भी इसी मुद्दे के साथ मदद :)


7

एक और स्थिति जिसमें आप यह त्रुटि प्राप्त कर सकते हैं, वह है:

मेरे पास एक ही त्रुटि थी और इसका कारण यह था कि एक INSERT बयान में जो UNION से डेटा प्राप्त करता था, स्तंभों का क्रम मूल तालिका से अलग था। यदि आप # तालिका 3 में आदेश को ए, बी, सी में बदलते हैं, तो आप त्रुटि को ठीक कर देंगे।

select a, b, c into #table1
from #table0

insert into #table1
    select a, b, c from #table2
    union
    select a, c, b from #table3

7

sql सर्वर पर आप SET ANSI_WARNINGS को इस तरह से उपयोग कर सकते हैं:

        using (SqlConnection conn = new SqlConnection("Data Source=XRAYGOAT\\SQLEXPRESS;Initial Catalog='Healthy Care';Integrated Security=True"))
        {
            conn.Open();

            using (var trans = conn.BeginTransaction())
            {
                try
                {
                    using cmd = new SqlCommand("", conn, trans))
                    { 

                    cmd.CommandText = "SET ANSI_WARNINGS OFF";
                    cmd.ExecuteNonQuery();

                    cmd.CommandText = "YOUR INSERT HERE";
                    cmd.ExecuteNonQuery();

                    cmd.Parameters.Clear();

                    cmd.CommandText = "SET ANSI_WARNINGS ON";
                    cmd.ExecuteNonQuery();

                    trans.Commit();
                    }
                }
                catch (Exception)
                {

                    trans.Rollback();
                }

            }

            conn.Close();

        }

7

मेरी भी यही समस्या थी। मेरे कॉलम की लंबाई बहुत कम थी।

आप जो कर सकते हैं, वह या तो लंबाई बढ़ाना है या उस पाठ को छोटा करना है जिसे आप डेटाबेस में रखना चाहते हैं।


7

वेब एप्लिकेशन सतह पर भी यह समस्या थी। आखिरकार पता चला कि विशिष्ट तालिका में SQL अद्यतन कथन से वही त्रुटि संदेश आता है।

अंत में तब पता चला कि संबंधित इतिहास तालिका (एस) में स्तंभ की परिभाषा nvarcharकुछ विशिष्ट मामलों में प्रकार की मूल तालिका स्तंभ की लंबाई को मैप नहीं करती है ।


4

टेबल में समस्याग्रस्त कॉलम का आकार बढ़ाने के बाद भी मुझे वही समस्या थी।

tl; dr: संबंधित तालिका प्रकारों में मिलान स्तंभों की लंबाई भी बढ़ानी पड़ सकती है।

मेरे मामले में, त्रुटि Microsoft Dynamics CRM में डेटा निर्यात सेवा से आ रही थी, जो CRM डेटा को SQL सर्वर DB या Azure SQL DB में सिंक करने की अनुमति देता है।

एक लंबी जाँच के बाद, मैंने निष्कर्ष निकाला कि डेटा एक्सपोर्ट सेवा को टेबल-वेलिड पैरामीटर का उपयोग करना चाहिए :

आप एक अस्थायी तालिका या कई मापदंडों को बनाए बिना, एक ट्रांसेक्ट-एसक्यूएल स्टेटमेंट या रूटीन जैसे डेटा की कई पंक्तियाँ भेजने के लिए टेबल-वैल्यूड पैरामीटर का उपयोग कर सकते हैं।

जैसा कि आप ऊपर दिए गए दस्तावेज़ में देख सकते हैं, डेटा अंतर्ग्रहण प्रक्रिया बनाने के लिए तालिका प्रकार का उपयोग किया जाता है:

CREATE TYPE LocationTableType AS TABLE (...);
CREATE PROCEDURE dbo.usp_InsertProductionLocation
  @TVP LocationTableType READONLY

दुर्भाग्य से, टेबल प्रकार को बदलने का कोई तरीका नहीं है, इसलिए इसे पूरी तरह से गिराया और फिर से बनाना होगा। चूंकि मेरी तालिका में 300 से अधिक क्षेत्र (300) हैं, इसलिए मैंने तालिका के कॉलम परिभाषा के आधार पर संबंधित तालिका प्रकार के निर्माण की सुविधा के लिए एक क्वेरी बनाई (बस [table_name]अपनी तालिका के नाम से प्रतिस्थापित करें):

SELECT 'CREATE TYPE [table_name]Type AS TABLE (' + STRING_AGG(CAST(field AS VARCHAR(max)), ',' + CHAR(10)) + ');' AS create_type
FROM (
  SELECT TOP 5000 COLUMN_NAME + ' ' + DATA_TYPE
      + IIF(CHARACTER_MAXIMUM_LENGTH IS NULL, '', CONCAT('(', IIF(CHARACTER_MAXIMUM_LENGTH = -1, 'max', CONCAT(CHARACTER_MAXIMUM_LENGTH,'')), ')'))
      + IIF(DATA_TYPE = 'decimal', CONCAT('(', NUMERIC_PRECISION, ',', NUMERIC_SCALE, ')'), '')
      AS field
  FROM INFORMATION_SCHEMA.COLUMNS
  WHERE TABLE_NAME = '[table_name]'
  ORDER BY ORDINAL_POSITION) AS T;

तालिका प्रकार को अपडेट करने के बाद, डेटा निर्यात सेवा ने एक बार फिर से ठीक से काम करना शुरू कर दिया! :)


2

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

आप कॉलम डेटा प्रकार का आकार बढ़ा सकते हैं या अपने डेटा की लंबाई कम कर सकते हैं।


1

एक अन्य स्थिति, जिसमें यह त्रुटि हो सकती है SQL सर्वर प्रबंधन स्टूडियो में है। यदि आपके टेबल में "टेक्स्ट" या "नेक्स्ट" फ़ील्ड हैं, तो कोई फर्क नहीं पड़ता कि आप किस तरह का फ़ील्ड अपडेट कर रहे हैं (उदाहरण के लिए बिट या पूर्णांक)। ऐसा लगता है कि स्टूडियो पूरे "ntext" फ़ील्ड को लोड नहीं करता है और संशोधित किए गए के बजाय सभी फ़ील्ड को अपडेट भी करता है। समस्या को हल करने के लिए, प्रबंधन स्टूडियो में क्वेरी से "टेक्स्ट" या "नेक्स्ट" फ़ील्ड को बाहर करें


1
कृपया अल्पविराम, अवधियों को जोड़कर और अपने व्याकरण की त्रुटियों को ठीक करके अपने उत्तर को पुनःप्रकाशित करने पर विचार करें।
जॉर्ज पैम्फिलिस

इस जवाब से मुझे मदद मिली - मेरे नवरच फ़ील्ड काफी बड़े हैं लेकिन मेरे पास एक नेक्स्ट फील्ड है। प्रबंधन स्टूडियो / एसएमएसएस में कुछ त्रुटि महसूस करता है।
शा

0

केविन पोप का स्वीकार किए गए जवाब के तहत टिप्पणी की मुझे जरूरत थी।

मेरे मामले में, समस्या यह थी कि मेरे पास मेरी मेज पर परिभाषित ट्रिगर थे जो एक ऑडिट टेबल में अपडेट / ट्रांजेक्शन सम्मिलित करेंगे, लेकिन ऑडिट टेबल में डेटा प्रकार बेमेल था जहां VARCHAR(MAX)मूल तालिका में एक स्तंभ संग्रहीत किया गया था VARCHAR(1)। ऑडिट टेबल, इसलिए मेरे ट्रिगर विफल हो रहे थे जब मैं VARCHAR(1)मूल तालिका कॉलम से अधिक कुछ भी सम्मिलित करूंगा और मुझे यह त्रुटि संदेश मिलेगा।


0

मैंने एक अलग रणनीति का इस्तेमाल किया, कुछ जगहों पर 8K आवंटित किए गए हैं। यहां केवल 50/100 का उपयोग किया जाता है।

declare @NVPN_list as table 
nvpn            varchar(50)
,nvpn_revision  varchar(5)
,nvpn_iteration INT
,mpn_lifecycle  varchar(30)
,mfr            varchar(100)
,mpn            varchar(50)
,mpn_revision   varchar(5)
,mpn_iteration  INT
-- ...
) INSERT INTO @NVPN_LIST 
SELECT  left(nvpn           ,50)    as nvpn
        ,left(nvpn_revision ,10)    as nvpn_revision
        ,nvpn_iteration
        ,left(mpn_lifecycle ,30)
        ,left(mfr           ,100)
        ,left(mpn           ,50)
        ,left(mpn_revision  ,5)
        ,mpn_iteration
        ,left(mfr_order_num ,50)
FROM [DASHBOARD].[dbo].[mpnAttributes] (NOLOCK) mpna

मुझे गति चाहिए थी, क्योंकि मेरे पास कुल 1M रिकॉर्ड है, और उनमें से 28K लोड करता हूं।

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