삽입하려고하면 오류, 문자열 또는 이진 데이터가 잘립니다.


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의 대답 @

당신이 메시지를 볼 때마다 ....

문자열 또는 이진 데이터가 잘립니다

스스로 생각하십시오 ... 필드가 내 데이터를 보유 할만큼 크지 않습니다.

customers 테이블의 테이블 구조를 확인하십시오. 하나 이상의 필드 길이가 삽입하려는 데이터를 보유하기에 충분히 크지 않다는 것을 알게 될 것입니다. 예를 들어 전화 필드가 varchar (8) 필드이고 11자를 입력하려고하면이 오류가 발생합니다.


16
또한 영향을받는 필드가 트리거 될 수 있습니다. 다행스럽게도 필자는이이이 ... 발생 다음 번에 기억
케빈 교황

14
어떤 필드가 잘릴 것인지 디버그에서 볼 수있는 방법이 있습니까?
DailyFrankPeter

이 오류는 고정 된 길이 후에 열이 데이터를 보유 할 수 없기 때문에 발생합니다. 예를 들어; Firstname nvarchar(5) 5자를 초과하여 삽입하면 오류가 발생합니다
Prakash

26

데이터 길이가 필드 길이보다 짧았지만이 문제가 발생했습니다. 기본 테이블의 트리거로 채워진 다른 로그 테이블 (감사 추적 용)에 문제가 있었으며 열 크기도 변경해야했습니다.


1
감사. tableA의 sql 열이 varchar (100)이기 때문입니다. 또한 열이 varchar (50) 인 다른 테이블에 삽입합니다.
Hnin Htet Htet Aung

1
내 경우에도 같은 문제가 발생했습니다. 방아쇠 조작은 범인이었습니다.
자동 조종 장치

19

INSERT명령문 중 하나 에서 너무 긴 문자열을 문자열 ( varchar또는 nvarchar) 열에 삽입하려고합니다 .

INSERT스크립트를 살펴본 결과 어느 범죄자인지 확실하지 않은 경우 오류 메시지 전에<1 row affected> 발생 하는 행을 계산할 수 있습니다 . 획득 한 숫자에 1을 더한 값은 명세서 번호를 제공합니다. 귀하의 경우 오류를 발생시키는 것은 두 번째 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

따라서 "기간"필드의 길이가 0이므로 삽입 작업이 실패했습니다. 수신 데이터 길이 인 "XXXXXX"(으)로 변경했으며 이제는 필드가 6이기 때문에 제대로 작동했습니다.

나는 이것이 같은 문제를 가진 사람을 돕기를 바랍니다 :)


7

이 오류가 발생할 수있는 또 다른 상황은 다음과 같습니다.

나는 같은 오류가 있었고 UNION에서 데이터를 수신 한 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 업데이트 명령문에서 동일한 오류 메시지가 나온다는 것을 알게되었습니다.

마지막으로 관련 기록 테이블의 열 정의가 nvarchar특정 경우 에 유형 의 원래 테이블 열 길이를 매핑하지 않았다는 것을 알아 냈습니다 .


4

테이블의 문제가있는 열의 크기를 늘린 후에도 동일한 문제가 발생했습니다.

tl; dr : 해당 테이블 형식에서 일치하는 열의 길이를 늘려야 할 수도 있습니다.

내 경우에는 Microsoft Dynamics CRM의 데이터 내보내기 서비스에서 오류가 발생하여 CRM 데이터를 SQL Server DB 또는 Azure SQL DB에 동기화 할 수 있습니다.

오랜 조사 끝에 데이터 내보내기 서비스가 Table-Valued Parameters 를 사용해야한다는 결론을 내 렸습니다 .

테이블 반환 매개 변수를 사용하면 임시 테이블이나 많은 매개 변수를 만들지 않고도 여러 행의 데이터를 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;

테이블 유형을 업데이트 한 후 데이터 내보내기 서비스가 다시 한 번 제대로 작동하기 시작했습니다! :)


2

저장 프로 시저를 실행하려고 할 때 일부 데이터를 추가 해야하는 열의 크기가 추가하려는 데이터보다 짧기 때문에 동일한 문제가 발생했습니다.

열 데이터 유형의 크기를 늘리거나 데이터 길이를 줄일 수 있습니다.


1

이 오류가 발생할 수있는 다른 상황은 SQL Server Management Studio에 있습니다. 테이블에 "text"또는 "ntext"필드가있는 경우 어떤 종류의 필드 (예 : 비트 또는 정수)를 업데이트하든 관계없이. Studio가 전체 "ntext"필드를로드하지 않고 수정 된 필드 대신 모든 필드를 업데이트하는 것 같습니다. 이 문제를 해결하려면 Management Studio의 쿼리에서 "text"또는 "ntext"필드를 제외하십시오.


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.