ошибка, строка или двоичные данные будут обрезаны при попытке вставить


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

Всякий раз, когда вы видите сообщение ....

Строка или двоичные данные будут проигнорированы

Подумайте сами ... Поле недостаточно большое, чтобы хранить мои данные.

Проверьте структуру таблицы для таблицы клиентов. Я думаю, вы обнаружите, что длина одного или нескольких полей НЕ достаточно велика для хранения данных, которые вы пытаетесь вставить. Например, если поле Phone является полем varchar (8), и вы пытаетесь ввести в него 11 символов, вы получите эту ошибку.


16
Также обратите внимание, что затронутые поля могут быть в триггере. Надеюсь, я запомню это в следующий раз, когда это произойдет ...
Кевин Поуп

14
Есть ли способ увидеть в отладке, какое поле будет усечено?
DailyFrankPeter

Эта ошибка вызвана тем, что ваш столбец не может содержать данные после фиксированной длины. Например; Firstname nvarchar(5) Если вы введете более 5 символов, вы получите сообщение об ошибке
Prakash

26

У меня была эта проблема, хотя длина данных была меньше, чем длина поля. Оказалось, что проблема заключалась в том, что была другая таблица журналов (для контрольного журнала), заполненная триггером на главной таблице, где размер столбца также нужно было изменить.


1
Спасибо. Мой был потому, что столбец sql в таблице A является varchar (100). Он также вставляется в другую таблицу, в которой столбцом является varchar (50).
Хнин Хтет Хтет Аунг

1
Та же проблема случилась и в моем случае. Спусковая операция была виновником.
автопилот

19

В одном из INSERTоператоров вы пытаетесь вставить слишком длинную строку в строку ( varcharили nvarchar) столбца.

Если неясно, кто INSERTявляется нарушителем, просто взглянув на сценарий, вы можете сосчитать <1 row affected>строки, которые появляются перед сообщением об ошибке. Полученный номер плюс один дает вам номер выписки. В вашем случае это, кажется, вторая вставка, которая выдает ошибку.


2
У меня та же проблема, как найти, какой столбец вызывает ошибку?
Катия Матос,

@ АндреБастос: Возможно, вы могли бы представить это как вопрос (если кто-то еще не сделал этого, и в этом случае может быть где-нибудь готовый ответ).
Андрей М

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, порядок столбцов отличался от исходной таблицы. Если вы измените порядок в # 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 или 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;

После обновления типа таблицы служба экспорта данных снова заработала! :)


2

Когда я попытался выполнить свою хранимую процедуру, у меня возникла та же проблема, потому что размер столбца, который мне нужно добавить для некоторых данных, короче, чем данные, которые я хочу добавить.

Вы можете увеличить размер типа данных столбца или уменьшить длину ваших данных.


1

Другая ситуация, в которой может возникнуть эта ошибка, - в SQL Server Management Studio. Если в вашей таблице есть поля «текст» или «текст», независимо от того, какой тип поля вы обновляете (например, бит или целое число). Кажется, что Studio не загружает целые поля «ntext», а также обновляет ВСЕ поля вместо измененных. Чтобы решить эту проблему, исключите поля «текст» или «текст» из запроса в Management Studio


1
Пожалуйста, попробуйте перефразировать ваш ответ, добавив запятые, точки и исправив свои грамматические ошибки.
Джордж Памфилис

Этот ответ помог мне - мои поля nvarchar достаточно велики, но у меня есть поле ntext. Кажется, какая-то ошибка в Management Studio / SMSS.
Ша

0

Комментарий Кевина Поупа под принятым ответом был тем, что мне было нужно.

Проблема, в моем случае, заключалась в том, что в моей таблице были определены триггеры, которые вставляли бы транзакции обновления / вставки в таблицу аудита, но в таблице аудита было несоответствие типов данных, где столбец с VARCHAR(MAX)исходной таблицей хранился, как VARCHAR(1)в таблица аудита, поэтому мои триггеры не срабатывали, когда я вставлял что-то большее, чем VARCHAR(1)в исходный столбец таблицы, и получал это сообщение об ошибке.


0

Я использовал другую тактику, поля которой выделены 8К в некоторых местах. Здесь используется только около 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

Мне нужна скорость, так как у меня всего 1 млн. Записей, и я загружаю 28K из них.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.