Строка SQL Server или двоичные данные будут усечены - PullRequest
119 голосов
/ 17 июня 2011

Я участвую в проекте по миграции данных. Я получаю следующую ошибку при попытке вставить данные из одной таблицы в другую таблицу (SQL Server 2005):

Сообщение 8152, Уровень 16, Состояние 13, Строка 1
Строковые или двоичные данные будут обрезаны.

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

Ответы [ 19 ]

1 голос
/ 20 апреля 2018

Да - «пинта в полпинты не пойдет». Мне не очень повезло (по какой-либо причине) с различными SP, предложенными людьми, НО, пока две таблицы находятся в одной БД (или вы можете поместить их в одну БД), вы можете использовать INFORMATION_SCHEMA. КОЛОННЫ, чтобы найти ошибочные поля, таким образом:

select c1.table_name,c1.COLUMN_NAME,c1.DATA_TYPE,c1.CHARACTER_MAXIMUM_LENGTH,c2.table_name,c2.COLUMN_NAME, c2.DATA_TYPE,c2.CHARACTER_MAXIMUM_LENGTH
from [INFORMATION_SCHEMA].[COLUMNS] c1
left join [INFORMATION_SCHEMA].[COLUMNS] c2 on 
c1.COLUMN_NAME=c2.COLUMN_NAME
where c1.TABLE_NAME='MyTable1'
and c2.TABLE_NAME='MyTable2'
--and c1.DATA_TYPE<>c2.DATA_TYPE
--and c1.CHARACTER_MAXIMUM_LENGTH <> c2.CHARACTER_MAXIMUM_LENGTH
order by c1.COLUMN_NAME

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

1 голос
/ 06 октября 2016

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

0 голосов
/ 19 октября 2018

Я написал полезную процедуру хранения, которая поможет идентифицировать и решить проблему усечения текста (строки или двоичные данные будут усечены) при использовании оператора INSERT SELECT.Он сравнивает только поля CHAR, VARCHAR, NCHAR и NVARCHAR и возвращает поле оценки по полю в случае возможной причины ошибки.

EXEC dbo.GetFieldStringTruncate SourceTableName, TargetTableName

Эта хранимая процедура ориентирована на проблему усечения текста при выполнении инструкции INSERT SELECT.

Работа этой хранимой процедуры зависит от того, кто ранее идентифицировал пользователя.ВСТАВИТЬ утверждение с проблемой.Затем вставка исходных данных в глобальную временную таблицу.Рекомендуется инструкция SELECT INTO.

Вы должны использовать одно и то же имя поля таблицы назначения в псевдониме каждого поля инструкции SELECT.

FUNCTIONКОД:

DECLARE @strSQL nvarchar(1000)
IF NOT EXISTS (SELECT * FROM dbo.sysobjects where id = OBJECT_ID(N'[dbo].[GetFieldStringTruncate]'))
    BEGIN
        SET @strSQL = 'CREATE PROCEDURE [dbo].[GetFieldStringTruncate] AS RETURN'
        EXEC sys.sp_executesql @strSQL
    END

GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

/*
------------------------------------------------------------------------------------------------------------------------
    Description:    
                    Syntax 
                    ---------------
                    dbo.GetFieldStringTruncate(SourceTable, TargetTable)
                    +---------------------------+-----------------------+
                    |   SourceTableName         |   VARCHAR(255)        |
                    +---------------------------+-----------------------+
                    |   TargetTableName         |   VARCHAR(255)        |
                    +---------------------------+-----------------------+

                    Arguments
                    ---------------
                    SourceTableName
                    The name of the source table. It should be a temporary table using double charp '##'. E.g. '##temp'

                    TargetTableName
                    The name of the target table. It is the table that receives the data used in the INSERT INTO stament.

                    Return Type
                    ----------------
                    Returns a table with a list of all the fields with the type defined as text and performs an evaluation indicating which field would present the problem of string truncation.

                    Remarks
                    ----------------
                    This stored procedure is oriented to the problem of text truncation when an INSERT SELECT statement is made.
                    The operation of this stored procedure depends on the user previously identifying the INSERT statement with the problem. Then inserting the source data into a global temporary table. The SELECT INTO statement is recommended.
                    You must use the same name of the field of the destination table in the alias of each field of the SELECT statement.

                    Examples
                    ====================================================================================================

                    --A. Test basic

                        IF EXISTS (SELECT * FROM sys.objects  WHERE OBJECT_ID = OBJECT_ID(N'[dbo].[tblDestino]') AND TYPE IN (N'U'))
                            DROP TABLE tblDestino

                        CREATE TABLE tblDestino
                        (
                            Id INT IDENTITY,
                            Field1 VARCHAR(10),
                            Field2 VARCHAR(12),
                            Field3 VARCHAR(11),
                            Field4 VARCHAR(16),
                            Field5 VARCHAR(5),
                            Field6 VARCHAR(1),
                            Field7 VARCHAR(1),
                            Field8 VARCHAR(6),
                            Field9 VARCHAR(6),
                            Field10 VARCHAR(50),
                            Field11 VARCHAR(50),
                            Field12 VARCHAR(50)
                        )

                        INSERT INTO dbo.tblDestino
                        (
                             Field1 ,
                             Field2 ,
                             Field3 ,
                             Field4 ,
                             Field5 ,
                             Field6 ,
                             Field7 ,
                             Field8 ,
                             Field9 ,
                             Field10 ,
                             Field11 ,
                             Field12
                            )
                        SELECT 
                             '123456789' , -- Field1 - varchar(10)
                             '123456789' , -- Field2 - varchar(12)
                             '123456789' , -- Field3 - varchar(11)
                             '123456789' , -- Field4 - varchar(16)
                             '123456789' , -- Field5 - varchar(5)
                             '123456789' , -- Field6 - varchar(1)
                             '123456789' , -- Field7 - varchar(1)
                             '123456789' , -- Field8 - varchar(6)
                             '123456789' , -- Field9 - varchar(6)
                             '123456789' , -- Field10 - varchar(50)
                             '123456789' , -- Field11 - varchar(50)
                             '123456789'  -- Field12 - varchar(50)
                        GO  

                    Result:
                        String or binary data would be truncated


                    *Here you get the truncation error. Then, we proceed to save the information in a global temporary table. 
                    *IMPORTANT REMINDER: You must use the same name of the field of the destination table in the alias of each field of the SELECT statement.


                    Process:

                        IF OBJECT_ID('tempdb..##TEMP') IS NOT NULL DROP TABLE ##TEMP
                        go
                        SELECT 
                             [Field1] = '123456789' ,
                             [Field2] = '123456789' ,
                             [Field3] = '123456789' ,
                             [Field4] = '123456789' ,
                             [Field5] = '123456789' ,
                             [Field6] = '123456789' ,
                             [Field7] = '123456789' ,
                             [Field8] = '123456789' ,
                             [Field9] = '123456789' ,
                             [Field10] = '123456789' ,
                             [Field11] = '123456789' ,
                             [Field12] = '123456789'  
                        INTO ##TEMP

                    Result:
                    (1 row(s) affected)

                    Test:
                        EXEC dbo.GetFieldStringTruncate @SourceTableName = '##TEMP', @TargetTableName = 'tblDestino'

                    Result:

                        (12 row(s) affected)
                        ORIGEN Nombre Campo        ORIGEN Maximo Largo  DESTINO Nombre Campo     DESTINO Tipo de campo   Evaluación
                        -------------------------- -------------------- ------------------------ ----------------------- -------------------------
                        Field1                     9                    02 - Field1              VARCHAR(10)             
                        Field2                     9                    03 - Field2              VARCHAR(12)             
                        Field3                     9                    04 - Field3              VARCHAR(11)             
                        Field4                     9                    05 - Field4              VARCHAR(16)             
                        Field5                     9                    06 - Field5              VARCHAR(5)              possible field with error
                        Field6                     9                    07 - Field6              VARCHAR(1)              possible field with error
                        Field7                     9                    08 - Field7              VARCHAR(1)              possible field with error
                        Field8                     9                    09 - Field8              VARCHAR(6)              possible field with error
                        Field9                     9                    10 - Field9              VARCHAR(6)              possible field with error
                        Field10                    9                    11 - Field10             VARCHAR(50)             
                        Field11                    9                    12 - Field11             VARCHAR(50)             
                        Field12                    9                    13 - Field12             VARCHAR(50)             

                    ====================================================================================================

    ------------------------------------------------------------------------------------------------------------

    Responsible:    Javier Pardo 
    Date:           October 19/2018
    WB tests:       Javier Pardo 

    ------------------------------------------------------------------------------------------------------------

*/

ALTER PROCEDURE dbo.GetFieldStringTruncate
(
    @SourceTableName AS VARCHAR(255)
    , @TargetTableName AS VARCHAR(255)
)
AS
BEGIN
    BEGIN TRY

        DECLARE @colsUnpivot AS NVARCHAR(MAX),
            @colsUnpivotConverted AS NVARCHAR(MAX),
           @query  AS NVARCHAR(MAX)

        SELECT @colsUnpivot = stuff((
                    SELECT DISTINCT ',' + QUOTENAME(col.NAME)
                    FROM tempdb.sys.tables tab
                    INNER JOIN tempdb.sys.columns col
                        ON col.object_id = tab.object_id
                    INNER JOIN tempdb.sys.types typ
                        ON col.system_type_id = TYP.system_type_id
                    WHERE tab.NAME = @SourceTableName
                    FOR XML path('')
                    ), 1, 1, '')
                ,@colsUnpivotConverted = stuff((
                    SELECT DISTINCT ',' + 'CONVERT(VARCHAR(MAX),' + QUOTENAME(col.NAME) + ') AS ' + QUOTENAME(col.NAME)
                    FROM tempdb.sys.tables tab
                    INNER JOIN tempdb.sys.columns col
                        ON col.object_id = tab.object_id
                    INNER JOIN tempdb.sys.types typ
                        ON col.system_type_id = TYP.system_type_id
                    WHERE tab.NAME = @SourceTableName
                    FOR XML path('')
                    ), 1, 1, '')


        --https://stackoverflow.com/questions/11158017/column-conflicts-with-the-type-of-other-columns-in-the-unpivot-list
        IF OBJECT_ID('tempdb..##TablaConMaximos') IS NOT NULL DROP TABLE ##TablaConMaximos

        set @query 
          = 'SELECT u.d AS colname, MAX(LEN(u.data)) as [maximo_largo]
            INTO ##TablaConMaximos
            FROM 
            (
                SELECT ' + @colsUnpivotConverted + '
                FROM ' + @SourceTableName + '
            ) T
            UNPIVOT
             (
                data
                for d in ('+ @colsunpivot +')
             ) u
             GROUP BY u.d'

        PRINT @query

        exec sp_executesql @query;

        ------------------------------------------------------------------------------------------------------------
        SELECT --'Nombre de campo' = RIGHT('00' + ISNULL(CONVERT(VARCHAR,col.column_id),''),2) + ' - ' + col.name + ' '
            --, 'Tipo de campo' = ISNULL(CONVERT(VARCHAR,upper(typ.name)),'') + '(' + ISNULL(CONVERT(VARCHAR,col.max_length),'') + ')'
            [ORIGEN Nombre Campo] = tcm.colname
            , [ORIGEN Maximo Largo] = tcm.maximo_largo
            , [DESTINO Nombre Campo] = DESTINO.[Nombre de campo]
            , [DESTINO Tipo de campo] = DESTINO.[Tipo de campo]
            , [Evaluación] = CASE WHEN DESTINO.maximo_largo < tcm.maximo_largo THEN 'possible field with error' ELSE '' END
            --, * 
        FROM tempdb.sys.tables tab
            INNER JOIN tempdb.sys.columns col
                ON col.object_id = tab.object_id
            INNER JOIN tempdb.sys.types typ
                ON col.system_type_id = TYP.system_type_id
            RIGHT JOIN 
                (
                    SELECT column_id
                        , [Nombre de campo] = RIGHT('00' + ISNULL(CONVERT(VARCHAR,col.column_id),''),2) + ' - ' + col.name + ' '
                        , [Tipo de campo] = ISNULL(CONVERT(VARCHAR,upper(typ.name)),'') + '(' + ISNULL(CONVERT(VARCHAR,col.max_length),'') + ')'
                        , [maximo_largo] = col.max_length
                        , [colname] = col.name
                    FROM sys.tables tab
                        INNER JOIN sys.columns col
                            ON col.object_id = tab.object_id
                        INNER JOIN sys.types typ
                            ON col.system_type_id = TYP.system_type_id
                    WHERE tab.NAME = @TargetTableName
                ) AS DESTINO
                    ON col.name = DESTINO.colname
            INNER JOIN ##TablaConMaximos tcm
                ON tcm.colname = DESTINO.colname

        WHERE tab.NAME = @SourceTableName
            AND typ.name LIKE '%char%'
        ORDER BY col.column_id

    END TRY
    BEGIN CATCH
        SELECT 'Internal error ocurred' AS Message
    END CATCH   

END

На данный момент поддерживаются только типы данных CHAR, VARCHAR, NCHAR и NVARCHAR .Вы можете найти последнюю версию этого кода в следующей ссылке ниже, и мы помогаем друг другу улучшить ее. GetFieldStringTruncate.sql

https://gist.github.com/jotapardo/210e85338f87507742701aa9d41cc51d

0 голосов
/ 30 января 2015

это также может произойти, если у вас нет соответствующих разрешений

0 голосов
/ 27 апреля 2018

Вот немного другой ответ. Все имена и длины столбцов могут совпадать, но, возможно, вы указали столбцы в неправильном порядке в своем операторе SELECT. Скажем, у tableX и tableY есть столбцы с одинаковыми именами, но в разном порядке

0 голосов
/ 28 марта 2017

Эта ошибка выдается, когда в столбец таблицы накладывается ограничение [в основном длина]. , Например. если схема базы данных для столбца myColumn имеет вид CHAR (2), то при вызове из любого вашего приложения для вставки значения необходимо передать строку длины два.

Ошибка в основном говорит об этом; Строка длиной три и выше не соответствует ограничениям длины, заданным схемой базы данных. Вот почему SQL Server предупреждает и выдает ошибку потери данных / усечения.

0 голосов
/ 29 января 2017

Пожалуйста, попробуйте следующий код:

CREATE TABLE [dbo].[Department](
    [Department_name] char(10) NULL
)

INSERT INTO [dbo].[Department]([Department_name]) VALUES  ('Family Medicine')
--error will occur

 ALTER TABLE [Department] ALTER COLUMN [Department_name] char(50)

INSERT INTO [dbo].[Department]([Department_name]) VALUES  ('Family Medicine')

select * from [Department]
0 голосов
/ 06 октября 2016

У меня была похожая проблема.Я копировал данные из одной таблицы во все идентичные таблицы, кроме имени.

В конце концов я сбросил исходную таблицу во временную таблицу с помощью инструкции SELECT INTO.

SELECT *
INTO TEMP_TABLE
FROM SOURCE_TABLE;

Я сравнил схему исходной таблицы с временной таблицей.Я обнаружил, что один из столбцов был varchar(4000), когда я ожидал varchar(250).

ОБНОВЛЕНИЕ: Проблема varchar (4000) может быть объяснена здесь в случае, если вы заинтересованы:

Для Nvarchar (Max) я получаю только 4000 символов в TSQL?

Надеюсь, это поможет.

0 голосов
/ 24 августа 2016

Я использовал пустую строку «» при создании таблицы и затем получал сообщение об ошибке «Сообщение 8152, строка или двоичные данные будут обрезаны» при последующем обновлении.Это происходило из-за значения обновления, содержащего 6 символов, которое было больше ожидаемого определения столбца.Я использовал «ПРОБЕЛ», чтобы обойти это только потому, что знал, что я буду обновлять массово после первоначального создания данных, то есть столбец не будет оставаться пустым долго.

ТАК БОЛЬШАЯ ПРОСМОТР ЗДЕСЬ: Это не такособенно удобное решение, но полезно в случае, когда вы собираете набор данных, например, для одноразовых запросов на интеллектуальные данные, когда вы создаете таблицу для интеллектуального анализа данных, применяете некоторую массовую обработку / интерпретацию и сохраняете результаты до и после для последующего сравнения/добыча полезных ископаемых.Это частое явление в моей работе.

Вы можете изначально заполнить, используя ключевое слово SPACE, например

    select 
           Table1.[column1]
          ,Table1.[column2]
          ,SPACE(10) as column_name
    into table_you_are_creating
    from Table1
    where ...

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...