dữ liệu lỗi, chuỗi hoặc nhị phân sẽ bị cắt bớt khi cố gắng chèn


250

Tôi đang chạy tệp data.bat với các dòng sau:

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

Nội dung của tệp data.sql là:

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

Có 8 dòng tương tự để thêm hồ sơ.

Khi tôi chạy này với start> run> cmd> c:\data.bat, tôi nhận được thông báo lỗi này:

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>

Ngoài ra, tôi là một newbie rõ ràng, nhưng những gì làm Level #, và state #trung bình, và làm thế nào để tìm kiếm các thông báo lỗi như một ở trên: 8152?

Câu trả lời:


609

Từ câu trả lời của @ gmmastros

Bất cứ khi nào bạn nhìn thấy tin nhắn ....

Chuỗi hoặc dữ liệu nhị phân sẽ được rút ngắn

Hãy tự suy nghĩ ... Trường KHÔNG đủ lớn để chứa dữ liệu của tôi.

Kiểm tra cấu trúc bảng cho bảng khách hàng. Tôi nghĩ bạn sẽ thấy rằng độ dài của một hoặc nhiều trường KHÔNG đủ lớn để chứa dữ liệu bạn đang cố gắng chèn. Ví dụ: nếu trường Điện thoại là trường varchar (8) và bạn cố gắng đặt 11 ký tự vào đó, bạn sẽ gặp lỗi này.


16
Cũng lưu ý rằng các trường bị ảnh hưởng có thể nằm trong một kích hoạt. Hy vọng tôi nhớ điều này vào lần tới khi điều này xảy ra ...
Kevin Pope

14
Có cách nào để xem trong gỡ lỗi trường nào sẽ bị cắt không?
DailyFrankPeter

Lỗi này là do cột của bạn không thể giữ dữ liệu sau thời lượng bạn đã sửa. Ví dụ; Firstname nvarchar(5) Nếu bạn chèn nhiều hơn 5 ký tự, bạn sẽ gặp lỗi
Prakash

26

Tôi gặp vấn đề này mặc dù chiều dài dữ liệu ngắn hơn chiều dài trường. Hóa ra vấn đề là có một bảng nhật ký khác (đối với dấu vết kiểm toán), được điền bởi một trình kích hoạt trên bảng chính, trong đó kích thước cột cũng phải được thay đổi.


1
Cảm ơn. Của tôi là vì cột sql trong bảngA là varchar (100). Nó cũng chèn vào một bảng khác, trong đó, cột là varchar (50).
Hnin Htet Htet Aung

1
Vấn đề tương tự cũng xảy ra trong trường hợp của tôi. Một hoạt động kích hoạt là thủ phạm.
lái tự động

19

Trong một trong các INSERTcâu lệnh bạn đang cố gắng chèn một chuỗi quá dài vào cột ( varcharhoặc nvarchar).

Nếu không rõ ràng ai INSERTlà người vi phạm chỉ bằng cách nhìn vào tập lệnh, bạn có thể đếm các <1 row affected>dòng xảy ra trước thông báo lỗi. Số thu được cộng với một cho bạn số báo cáo. Trong trường hợp của bạn, nó dường như là CHERTN thứ hai tạo ra lỗi.


2
Tôi có cùng một vấn đề, làm thế nào để tìm cột nào gây ra lỗi?
Cátia Matos

@ AndréBastos: Có lẽ bạn có thể gửi câu hỏi đó dưới dạng câu hỏi (trừ khi người khác đã làm điều đó, trong trường hợp đó có thể có câu trả lời sẵn sàng cho câu hỏi đó ở đâu đó).
Andriy M

11

Một số dữ liệu của bạn không thể vừa với cột cơ sở dữ liệu của bạn (nhỏ). Không dễ để tìm thấy những gì sai. Nếu bạn sử dụng C # và Linq2Sql, bạn có thể liệt kê trường sẽ bị cắt ngắn:

Tạo lớp trợ giúp đầu tiên:

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);
                    }

                }
            }
        }
    }
}

Sau đó, chuẩn bị trình bao bọc cho SendChanges:

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;
        }
    }
}

Chuẩn bị xử lý ngoại lệ toàn cầu và chi tiết cắt bớt nhật ký:

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

Cuối cùng sử dụng mã:

Datamodel.SubmitChangesWithDetailException();

9

Chỉ muốn đóng góp với thông tin bổ sung: Tôi có cùng một vấn đề và đó là do trường không đủ lớn cho dữ liệu đến và chủ đề này đã giúp tôi giải quyết nó (câu trả lời hàng đầu làm rõ tất cả).

NHƯNG điều rất quan trọng là phải biết những lý do có thể gây ra nó là gì.

Trong trường hợp của tôi, tôi đã tạo bảng với một trường như thế này:

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

Do đó, trường "Thời gian" có độ dài bằng 0 và khiến các thao tác Chèn không thành công. Tôi đã thay đổi nó thành "XXXXXX", đó là độ dài của dữ liệu đến và hiện tại nó đã hoạt động bình thường (vì trường hiện có 6 lentgh).

Tôi hy vọng điều này sẽ giúp bất cứ ai có cùng một vấn đề :)


7

Một tình huống khác trong đó bạn có thể nhận được lỗi này là:

Tôi đã có cùng một lỗi và lý do là trong một câu lệnh INSERT nhận dữ liệu từ UNION, thứ tự của các cột khác với bảng gốc. Nếu bạn thay đổi thứ tự trong # bảng3 thành a, b, c, bạn sẽ sửa lỗi.

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

trên máy chủ sql, bạn có thể sử dụng TẮT ANSI_WARNINGS TẮT như thế này:

        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

Tôi gặp vấn đề tương tự. Độ dài cột của tôi quá ngắn.

Những gì bạn có thể làm là tăng độ dài hoặc rút ngắn văn bản bạn muốn đưa vào cơ sở dữ liệu.


7

Cũng có vấn đề này xảy ra trên bề mặt ứng dụng web. Cuối cùng phát hiện ra rằng thông báo lỗi tương tự xuất phát từ câu lệnh cập nhật SQL trong bảng cụ thể.

Cuối cùng, sau đó tìm ra rằng định nghĩa cột trong (các) bảng lịch sử liên quan không ánh xạ độ dài cột của bảng gốc nvarchartrong một số trường hợp cụ thể.


4

Tôi đã có cùng một vấn đề, ngay cả sau khi tăng kích thước của các cột có vấn đề trong bảng.

tl; dr: Độ dài của các cột khớp trong Các loại bảng tương ứng cũng có thể cần phải tăng lên.

Trong trường hợp của tôi, lỗi xuất phát từ dịch vụ Xuất dữ liệu trong Microsoft Dynamics CRM, cho phép dữ liệu CRM được đồng bộ hóa với SQL Server DB hoặc Azure SQL DB.

Sau một cuộc điều tra dài, tôi đã kết luận rằng dịch vụ Xuất dữ liệu phải được sử dụng Tham số có giá trị theo bảng :

Bạn có thể sử dụng các tham số có giá trị bảng để gửi nhiều hàng dữ liệu tới câu lệnh Transact-SQL hoặc một thường trình, chẳng hạn như một thủ tục hoặc hàm được lưu trữ, mà không tạo một bảng tạm thời hoặc nhiều tham số.

Như bạn có thể thấy trong tài liệu trên, Các loại bảng được sử dụng để tạo thủ tục nhập dữ liệu:

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

Thật không may, không có cách nào để thay đổi Loại bảng, vì vậy nó phải được loại bỏ & tái tạo hoàn toàn. Vì bảng của tôi có hơn 300 trường (), tôi đã tạo một truy vấn để tạo thuận lợi cho việc tạo Loại bảng tương ứng dựa trên định nghĩa cột của bảng (chỉ cần thay thế [table_name]bằng tên bảng của bạn):

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;

Sau khi cập nhật Loại bảng, dịch vụ Xuất dữ liệu bắt đầu hoạt động bình thường trở lại! :)


2

Khi tôi cố gắng thực hiện thủ tục được lưu trữ của mình, tôi gặp vấn đề tương tự vì kích thước của cột mà tôi cần thêm một số dữ liệu ngắn hơn dữ liệu tôi muốn thêm.

Bạn có thể tăng kích thước của kiểu dữ liệu cột hoặc giảm độ dài của dữ liệu của bạn.


1

Một tình huống khác, trong đó lỗi này có thể xảy ra là trong SQL Server Management Studio. Nếu bạn có các trường "văn bản" hoặc "ntext" trong bảng của mình, bất kể bạn đang cập nhật loại trường nào (ví dụ: bit hoặc số nguyên). Có vẻ như Studio không tải toàn bộ các trường "ntext" và cũng cập nhật TẤT CẢ các trường thay vì trường đã sửa đổi. Để giải quyết vấn đề, loại trừ các trường "văn bản" hoặc "ntext" khỏi truy vấn trong Management Studio


1
Vui lòng xem xét lại câu trả lời của bạn bằng cách thêm dấu phẩy, dấu chấm và sửa lỗi ngữ pháp của bạn.
George Pamfilis

Câu trả lời này đã giúp tôi - các trường nvarchar của tôi đủ lớn nhưng tôi có một trường ntext. Có vẻ là một số lỗi trong Management Studio / SMSS.
Sha

0

Nhận xét của Kevin Pope dưới câu trả lời được chấp nhận là những gì tôi cần.

Vấn đề, trong trường hợp của tôi, là tôi có các trình kích hoạt được xác định trên bảng sẽ chèn các giao dịch cập nhật / chèn vào bảng kiểm toán, nhưng bảng kiểm toán có kiểu dữ liệu không khớp trong đó một cột VARCHAR(MAX)trong bảng gốc được lưu trữ như VARCHAR(1)trong bảng kiểm toán, do đó, trình kích hoạt của tôi đã thất bại khi tôi sẽ chèn bất cứ thứ gì lớn hơn VARCHAR(1)vào cột bảng gốc và tôi sẽ nhận được thông báo lỗi này.


0

Tôi đã sử dụng một chiến thuật khác, các trường được phân bổ 8K ở một số nơi. Ở đây chỉ có khoảng 50/100 được sử dụng.

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

Tôi muốn tốc độ, vì tôi có tổng số hồ sơ 1M và tải 28K trong số đó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.