ข้อผิดพลาดสตริงหรือข้อมูลไบนารีจะถูกตัดทอนเมื่อพยายามแทรก


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 #หมายความว่าอย่างไรและฉันจะค้นหาข้อความแสดงข้อผิดพลาดเช่นข้อความข้างต้นได้อย่างไร: 8152

คำตอบ:


609

จากคำตอบของ @ gmmastros

เมื่อใดก็ตามที่คุณเห็นข้อความ ....

ข้อมูลสตริงหรือไบนารีจะถูกตัดทอน

คิดกับตัวเอง ... ฟิลด์นี้ไม่ใหญ่พอที่จะเก็บข้อมูลของฉัน

ตรวจสอบโครงสร้างตารางสำหรับตารางลูกค้า ฉันคิดว่าคุณจะพบว่าความยาวของฟิลด์หนึ่งหรือมากกว่านั้นไม่ใหญ่พอที่จะเก็บข้อมูลที่คุณพยายามแทรก ตัวอย่างเช่นหากฟิลด์โทรศัพท์เป็นฟิลด์ varchar (8) และคุณพยายามใส่อักขระ 11 ตัวคุณจะได้รับข้อผิดพลาดนี้


16
โปรดทราบว่าฟิลด์ที่ได้รับผลกระทบอาจอยู่ในทริกเกอร์ หวังว่าฉันจะจำสิ่งนี้ได้ในครั้งต่อไปที่สิ่งนี้จะเกิดขึ้น ...
Kevin Pope

14
มีวิธีการดูในการแก้ปัญหาใดฟิลด์จะถูกตัดทอน?
DailyFrankPeter

ข้อผิดพลาดนี้เป็นเพราะคอลัมน์ของคุณไม่สามารถเก็บข้อมูลหลังจากความยาวที่คุณแก้ไข เช่น; Firstname nvarchar(5) หากคุณใส่มากกว่า 5 ตัวอักษรคุณจะได้รับข้อผิดพลาด
Prakash

26

ฉันมีปัญหานี้แม้ว่าความยาวของข้อมูลจะสั้นกว่าความยาวของเขตข้อมูล มันกลับกลายเป็นว่าปัญหาเกิดขึ้นกับตารางบันทึกอื่น (สำหรับหลักฐานการตรวจสอบ) ซึ่งเต็มไปด้วยทริกเกอร์ในตารางหลักซึ่งต้องเปลี่ยนขนาดคอลัมน์ด้วย


1
ขอบคุณ ฉันเป็นเพราะคอลัมน์ sql ใน tableA คือ varchar (100) นอกจากนี้ยังแทรกลงในตารางอื่นซึ่งคอลัมน์คือ varchar (50)
Hnin Htet Htet Aung

1
ปัญหาเดียวกันก็เกิดขึ้นในกรณีของฉันเช่นกัน การดำเนินการเรียกเป็นผู้กระทำผิด
autopilot

19

ในหนึ่งในINSERTคำสั่งที่คุณพยายามแทรกสตริงยาวเกินไปในคอลัมน์สตริง ( varcharหรือnvarchar)

หากไม่ชัดเจนว่าINSERTเป็นผู้กระทำความผิดโดยดูเพียงสคริปต์คุณสามารถนับ<1 row affected>บรรทัดที่เกิดขึ้นก่อนข้อความแสดงข้อผิดพลาด จำนวนที่ได้รับบวกหนึ่งให้หมายเลขคำสั่ง ในกรณีของคุณดูเหมือนว่าจะเป็น INSERT ที่สองที่สร้างข้อผิดพลาด


2
ฉันมีปัญหาเดียวกันวิธีการค้นหาคอลัมน์ที่ทำให้เกิดข้อผิดพลาด?
Cátia Matos

@ AndréBastos: บางทีคุณสามารถส่งเป็นคำถาม (เว้นแต่มีคนอื่นทำไปแล้วซึ่งในกรณีนี้อาจมีคำตอบที่พร้อมให้ที่อื่น)
Andriy M

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 ที่รับข้อมูลจากยูเนี่ยนลำดับของคอลัมน์นั้นแตกต่างจากตารางต้นฉบับ หากคุณเปลี่ยนลำดับใน # table3 เป็น a, b, c คุณจะแก้ไขข้อผิดพลาด

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 OFF ดังนี้:

        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 update ในตารางที่ระบุ

ในที่สุดก็พบว่าคำจำกัดความคอลัมน์ในตารางประวัติที่เกี่ยวข้องไม่ได้แมปความยาวคอลัมน์คอลัมน์ดั้งเดิมของnvarcharประเภทในบางกรณี


4

ฉันมีปัญหาเดียวกันแม้หลังจากเพิ่มขนาดของคอลัมน์ที่มีปัญหาในตารางแล้ว

tl; dr: ความยาวของคอลัมน์ที่ตรงกันในประเภทตารางที่เกี่ยวข้องอาจต้องเพิ่มขึ้นด้วย

ในกรณีของฉันข้อผิดพลาดมาจากบริการส่งออกข้อมูลใน Microsoft Dynamics CRM ซึ่งอนุญาตให้ซิงค์ข้อมูล CRM กับ SQL Server DB หรือ Azure SQL DB

หลังจากการตรวจสอบที่ยาวนานฉันสรุปว่าบริการส่งออกข้อมูลจะต้องใช้พารามิเตอร์ที่มีค่าเป็นตาราง :

คุณสามารถใช้พารามิเตอร์ที่มีค่าเป็นตารางเพื่อส่งข้อมูลหลายแถวไปยังคำสั่ง Transact-SQL หรือชุดคำสั่งเช่นขั้นตอนหรือฟังก์ชันที่เก็บไว้โดยไม่ต้องสร้างตารางชั่วคราวหรือพารามิเตอร์จำนวนมาก

ดังที่คุณเห็นในเอกสารข้างต้นชนิดของตารางถูกใช้เพื่อสร้างขั้นตอนการนำเข้าข้อมูล:

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

น่าเสียดายที่ไม่มีวิธีในการเปลี่ยนประเภทตารางดังนั้นจึงต้องลบ & สร้างใหม่ทั้งหมด เนื่องจากตารางของฉันมีฟิลด์มากกว่า 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;

หลังจากอัปเดต Table Type แล้วบริการส่งออกข้อมูลก็เริ่มทำงานอีกครั้งอย่างถูกต้อง! :)


2

เมื่อฉันพยายามเรียกใช้กระบวนงานที่เก็บไว้ของฉันฉันมีปัญหาเดียวกันเนื่องจากขนาดของคอลัมน์ที่ฉันต้องการเพิ่มข้อมูลบางอย่างนั้นสั้นกว่าข้อมูลที่ฉันต้องการเพิ่ม

คุณสามารถเพิ่มขนาดของชนิดข้อมูลคอลัมน์หรือลดความยาวของข้อมูลของคุณ


1

สถานการณ์อื่นซึ่งข้อผิดพลาดนี้อาจเกิดขึ้นอยู่ใน SQL Server Management Studio หากคุณมีฟิลด์ "ข้อความ" หรือ "ntext" ในตารางของคุณไม่ว่าคุณจะอัปเดตฟิลด์ประเภทใด (เช่นบิตหรือจำนวนเต็ม) ดูเหมือนว่าสตูดิโอจะไม่โหลดฟิลด์ "ntext" ทั้งหมดและยังอัปเดตฟิลด์ทั้งหมดแทนการแก้ไข ในการแก้ปัญหาให้ยกเว้นฟิลด์ "text" หรือ "ntext" จากเคียวรีใน Management Studio


1
โปรดพิจารณาการปรับปรุงคำตอบของคุณใหม่โดยเพิ่มเครื่องหมายจุลภาคระยะเวลาและแก้ไขข้อผิดพลาดทางไวยากรณ์ของคุณ
George Pamfilis

คำตอบนี้ช่วยฉัน - ฟิลด์ nvarchar ของฉันมีขนาดใหญ่พอ แต่ฉันมีฟิลด์ ntext ดูเหมือนว่าจะมีข้อผิดพลาดใน Management Studio / SMSS
Sha

0

ความคิดเห็นของ Kevin Popeภายใต้คำตอบที่ยอมรับคือสิ่งที่ฉันต้องการ

ปัญหาที่เกิดขึ้นในกรณีของฉันเป็นที่ฉันมีทริกเกอร์ที่กำหนดไว้บนโต๊ะของฉันที่จะแทรกปรับปรุง / แทรกการทำธุรกรรมลงในตารางการตรวจสอบ แต่ตารางการตรวจสอบมีไม่ตรงกันชนิดข้อมูลที่คอลัมน์ที่มี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 ของพวกเขา

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.