Cadeia de caracteres do SQL Server ou dados binários seriam truncados


149

Estou envolvido em um projeto de migração de dados. Estou recebendo o seguinte erro ao tentar inserir dados de uma tabela em outra tabela (SQL Server 2005):

A mensagem 8152, nível 16, estado 13, linha 1,
seqüência de caracteres ou dados binários seria truncada.

As colunas de dados de origem correspondem ao tipo de dados e estão dentro das definições de comprimento das colunas da tabela de destino; portanto, não sei o que pode estar causando esse erro.


Você se importaria de publicar algum código e informações sobre cada tabela?
precisa

As tabelas são muito grandes - portanto, postarei apenas a parte das definições de tabela envolvidas e o código - isso é aceitável?
Jim Evans

As definições da tabela e o código seriam ótimos.
IAmTimCorey

1
A última vez em que tive esse problema, foi com o gatilho, O gatilho estava inserindo dados em uma tabela de auditoria. vale a pena verificar gatilho também.
Sachin Vishwakarma

Respostas:


185

Você precisará publicar as definições da tabela para as tabelas de origem e destino para que possamos descobrir onde está o problema, mas a linha inferior é que uma de suas colunas na tabela de origem é maior que as colunas de destino . Pode ser que você esteja alterando os formatos de uma maneira que não conhecia. O modelo de banco de dados do qual você está saindo é importante para descobrir isso também.


1
Por meu comentário acima - vindo logo :)
Jim Evans

3
Eu havia enfrentado o mesmo problema e tive que comparar todos os tipos e tamanhos de colunas de ambas as tabelas para corrigir o problema.
Aziz Shaikh

1
Depois de executar o exercício de reunir as definições parciais da tabela e obter o código sproc, a coluna incorreta saltou para mim como um raio ... Obrigado a todos por sua contribuição.
perfil completo de Jim Evans

Não posso contar quantas vezes eu fiz a mesma coisa. Que bom que você conseguiu resolver seu problema.
IAmTimCorey

Marquei você primeira resposta como a resposta porque era o que me levou a encontrar a resposta :)
Jim Evans

86

Como já foi dito, um dos tipos de dados de suas colunas na tabela de origem é maior que as colunas de destino.

Uma solução simples é simplesmente desativar o aviso e permitir que o truncamento ocorra. Portanto, se você estiver recebendo esse erro, mas com certeza é aceitável que os dados em seu banco de dados / tabela antigo sejam truncados (cortados no tamanho), basta fazer o seguinte;

SET ANSI_WARNINGS  OFF;
-- Your insert TSQL here.
SET ANSI_WARNINGS ON;

Como acima, lembre-se sempre de ativar os avisos novamente depois. Eu espero que isso ajude.


1
Você me salvou algumas horas de trabalho! Tome todos os meus agradecimentos!
Urasquirrel

Da mesma forma aqui. Às vezes, tenho que armazenar dados em uma tabela de, digamos, um serviço da web, onde o tipo de dados é definido apenas como uma "string". Eu não posso fazer tudo o que um Varchar (MAX) ...
Curt

61

O problema é bastante simples: uma ou mais das colunas na consulta de origem contêm dados que excedem o comprimento da coluna de destino. Uma solução simples seria levar sua consulta de origem e executar Max(Len( source col ))em cada coluna. Ou seja,

Select Max(Len(TextCol1))
    , Max(Len(TextCol2))
    , Max(Len(TextCol3))
    , ...
From ...

Em seguida, compare esses comprimentos com os comprimentos de tipo de dados na sua tabela de destino. Pelo menos um excede o comprimento da coluna de destino.

Se você está absolutamente certo de que esse não deve ser o caso e não se importa se não for o caso , outra solução é converter à força as colunas de consulta de origem no comprimento de destino (o que truncará quaisquer dados que sejam muito longos):

Select Cast(TextCol1 As varchar(...))
    , Cast(TextCol2 As varchar(...))
    , Cast(TextCol3 As varchar(...))
    , ...
From ...

Meu processo diário começou a ser interrompido com esse erro. Os dados inseridos sempre eram curtos o suficiente para caber e eu sempre tinha outras linhas (na Tabela da qual eu estava retirando) com seqüências de caracteres grandes demais que nunca foram inseridas por causa do meu filtro. Talvez um índice tenha sido reconstruído ou as estatísticas tenham sido atualizadas, mas o fantasma na máquina decidiu um dia não gostar mais do plano de consulta, porque seguiu um caminho no qual os dados (que eram muito amplos) "poderiam" ser inserido antes de ser filtrado pelo Predicado na Cláusula Where. Para contornar isso, usei LEFT () em vez de CAST - apenas menos caracteres para digitar.
MikeTeeVee

1
Obrigado Thomas, isso é estranho, mesmo que eu não tenha dados muito longos, ainda tenho que convertê-lo no novo tamanho da coluna de destino, assim que fiz isso funcionou.
317 Michelle

15

O SQL Server 2019 finalmente retornará uma mensagem de erro mais significativa.

Os dados binários ou de string seriam truncados => aprimoramentos da mensagem de erro

se você tiver esse erro (em produção), não é óbvio ver de qual coluna ou linha esse erro vem e como localizá-lo exatamente.

Para habilitar um novo comportamento, você precisa usar DBCC TRACEON(460). Novo texto de erro de sys.messages:

SELECT * FROM sys.messages WHERE message_id = 2628

2628 - Os dados de sequência ou binários seriam truncados na tabela '%. * Ls', coluna '%. * Ls'. Valor truncado: '%. * Ls'.

Dados de cadeia ou binários seriam truncados: substituindo o erro infame 8152

Esta nova mensagem também é suportada para o SQL Server 2017 CU12 (e em uma próxima CU do SQL Server 2016 SP2), mas não por padrão. É necessário ativar o sinalizador de rastreamento 460 para substituir a mensagem ID 8152 por 2628, no nível da sessão ou do servidor.

Observe que, por enquanto, mesmo no SQL Server 2019 CTP 2.0, o mesmo sinalizador de rastreamento 460 precisa estar ativado. Em uma versão futura do SQL Server 2019, a mensagem 2628 substituirá a mensagem 8152 por padrão.


O SQL Server 2017 CU12 também oferece suporte a esse recurso.

Melhoria: Substituição opcional da mensagem "Seqüência de caracteres ou dados binários seriam truncados" com informações estendidas no SQL Server 2017

Esta atualização do SQL Server 2017 apresenta uma mensagem opcional que contém as seguintes informações de contexto adicionais.

Msg 2628, Level 16, State 6, Procedure ProcedureName, Line Linenumber
String or binary data would be truncated in table '%.*ls', column '%.*ls'.
Truncated value: '%.*ls'.

O novo ID da mensagem é 2628. Essa mensagem substitui a mensagem 8152 em qualquer saída de erro se o sinalizador de rastreamento 460 estiver ativado.

db <> demo de violino


ALTERAR A CONFIGURAÇÃO DO ESCOPO DA BASE DE DADOS

VERBOSE_TRUNCATION_WARNINGS = {LIGADO | FORA }

Aplica-se a: SQL Server (iniciando no SQL Server 2019 (15.x)) e banco de dados SQL do Azure

Permite ativar ou desativar a nova String ou os dados binários seriam truncados na mensagem de erro. O SQL Server 2019 (15.x) apresenta uma nova mensagem de erro mais específica (2628) para este cenário:

String or binary data would be truncated in table '%.*ls', column'%.*ls'. Truncated value: '%.*ls'.

Quando definido como LIGADO no nível de compatibilidade de banco de dados 150, os erros de truncamento geram a nova mensagem de erro 2628 para fornecer mais contexto e simplificar o processo de solução de problemas.

Quando definido como OFF no nível de compatibilidade de banco de dados 150, os erros de truncamento geram a mensagem de erro anterior 8152.

Para o nível de compatibilidade do banco de dados 140 ou inferior, a mensagem de erro 2628 permanece uma mensagem de erro de aceitação que requer que o sinalizador de rastreamento 460 esteja ativado e essa configuração com escopo do banco de dados não tem efeito.


1
Este é agora também disponível para SQL Azure: azure.microsoft.com/en-gb/updates/...
Ian Kemp

7

Um outro motivo potencial para isso é se você tiver uma configuração de valor padrão para uma coluna que exceda o comprimento da coluna. Parece que alguém tocou uma coluna com um comprimento de 5, mas o valor padrão excedeu o comprimento de 5. Isso me deixou maluco, enquanto eu tentava entender por que não estava funcionando em nenhuma inserção, mesmo se tudo o que eu estava inserindo fosse. uma única coluna com um número inteiro 1. Como o valor padrão no esquema da tabela tinha esse valor violador, ele estragou tudo - o que eu acho que nos leva à lição aprendida - evite ter tabelas com os valores padrão no esquema. :)


1
Não acho que evitar valores padrão seja uma boa solução. Valores padrão são muito úteis. Eu não iria banco de dados resolve "problemas" causados por erros de digitação, removendo os valores padrão ...
Jacob H

3

Para os outros, verifique também o procedimento armazenado . No meu caso, no meu procedimento armazenado, CustomSearchdeclarei acidentalmente que não há comprimento suficiente para minha coluna; portanto, quando inseri um grande volume de dados, recebi esse erro, mesmo tendo um grande comprimento no meu banco de dados. Acabei de alterar o comprimento da minha coluna na minha pesquisa personalizada, o erro desaparece. Isso é apenas para lembrar. Obrigado.


isso é exatamente o que acontece comigo. as tabelas de origem / destino correspondem bem, mas o proc armazenado tinha uma tabela definida com menor comprimento e falhou lá. Obrigado!
Joy Walker

3

Este pode ser um erro desafiador. Aqui estão algumas anotações feitas em https://connect.microsoft.com/SQLServer/feedback/details/339410/ procure pelo comentário de AmirCharania.

Ajustei a resposta dada pelo AmirCharania para os dados selecionados em uma tabela real, em vez de uma temporária. Primeiro selecione seu conjunto de dados em uma tabela de desenvolvimento e execute o seguinte:

WITH CTE_Dev
AS (
    SELECT C.column_id
        ,ColumnName = C.NAME
        ,C.max_length
        ,C.user_type_id
        ,C.precision
        ,C.scale
        ,DataTypeName = T.NAME
    FROM sys.columns C
    INNER JOIN sys.types T ON T.user_type_id = C.user_type_id
    WHERE OBJECT_ID = OBJECT_ID('YOUR TARGET TABLE NAME HERE, WITH SCHEMA')
    )
    ,CTE_Temp
AS (
    SELECT C.column_id
        ,ColumnName = C.NAME
        ,C.max_length
        ,C.user_type_id
        ,C.precision
        ,C.scale
        ,DataTypeName = T.NAME
    FROM sys.columns C
    INNER JOIN sys.types T ON T.user_type_id = C.user_type_id
    WHERE OBJECT_ID = OBJECT_ID('YOUR TEMP TABLE NAME HERE, WITH SCHEMA')
    )
SELECT *
FROM CTE_Dev D
FULL OUTER JOIN CTE_Temp T ON D.ColumnName = T.ColumnName
WHERE ISNULL(D.max_length, 0) < ISNULL(T.max_length, 999)

Parece que a MS desligou o site do Connect. O novo link para esse problema é: feedback.azure.com/forums/908035-sql-server/suggestions/… ... ainda marcado como não planejado. Acho que o comentário a que você está se referindo foi (ironicamente) truncado quando a migração ocorreu.
SWalters - Restabelece Monica

Curiosamente, o problema foi aberto novamente com um título um pouco diferente: feedback.azure.com/forums/908035-sql-server/suggestions/… e foi listado como "Em revisão", então ainda há esperança.
SWalters - Restabelece Monica

3

Aqui está uma resposta um pouco diferente. Os nomes e os comprimentos das suas colunas podem corresponder, mas talvez você esteja especificando as colunas na ordem errada na sua instrução SELECT. Digamos que tableX e tableY tenham colunas com o mesmo nome, mas em ordem diferente


2

Hoje me deparei com esse problema e, na minha busca por uma resposta para esta mensagem de erro informativa mínima, também encontrei este link:

https://connect.microsoft.com/SQLServer/feedback/details/339410/please-fix-the-string-or-binary-data-would-be-truncated-message-to-give-the-column-name

Portanto, parece que a Microsoft não tem planos de expandir a mensagem de erro em breve.

Então eu me virei para outros meios.

Copiei os erros para o Excel:

(1 linha (s) afetada)

(1 linha (s) afetada)

(1 linha (s) afetada) Msg 8152, Nível 16, Estado 14, Linha 13 Seqüência de caracteres ou dados binários seriam truncados. A instrução foi encerrada.

(1 linha (s) afetada)

contei o número de linhas no excel, cheguei perto do contador de registros que causou o problema ... ajustei meu código de exportação para imprimir o SQL perto dele ... depois executei as inserções de 5 a 10 sql em torno do problema sql e conseguiu identificar o problema, ver a sequência que era muito longa, aumentar o tamanho dessa coluna e, em seguida, o grande arquivo de importação não teve problema.

Um pouco de um hack e uma solução alternativa, mas quando você sai com muito pouca escolha, você faz o que pode.


2

Sim, eu também estou enfrentando esse tipo de problema.

REMARKS VARCHAR(500)
to
REMARKS VARCHAR(1000)

Aqui, mudei o tamanho do arquivo OBSERVAÇÕES de 500 para 1000


2

Vou adicionar outra causa possível desse erro, apenas porque ninguém o mencionou e isso pode ajudar uma pessoa futura (uma vez que o OP encontrou sua resposta). Se a tabela na qual você está inserindo tiver gatilhos, pode ser que o gatilho esteja gerando o erro. Vi isso acontecer quando as definições de campo da tabela foram alteradas, mas as tabelas de auditoria não.


2

Sim - "um litro em um pote de meio litro não vai". Eu não tive muita sorte (por qualquer motivo) com os vários SPs que as pessoas sugeriram, mas desde que as duas tabelas estejam no mesmo banco de dados (ou você pode colocá-las no mesmo banco de dados), você pode usar o Information_SCHEMA. COLUNAS para localizar os campos errantes, assim:

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

Isso permitirá que você role para cima e para baixo, comparando os comprimentos dos campos à medida que avança. As seções comentadas permitem que você veja (uma vez descomentado, obviamente) se existem incompatibilidades de tipo de dados ou mostre especificamente aquelas que diferem no comprimento do campo - porque eu sou muito preguiçoso para rolar - esteja ciente de que tudo está baseado na fonte nomes de colunas que correspondem aos do destino.


Eu ia escrever algo assim, mas você apenas facilitou. muito útil e funcionou como um encanto. Consegui usá-lo para comparar uma tabela com mais de 90 colunas e duas delas saltaram imediatamente. Obrigado!
21718 Joy JoyJul

1

Eu estava usando a string vazia '' na criação da tabela e, em seguida, recebi o erro 'Msg 8152, String ou dados binários seriam truncados' na atualização subsequente. Isso estava acontecendo devido ao valor de atualização contendo 6 caracteres e sendo maior que a definição da coluna prevista. Eu usei o "ESPAÇO" para contornar isso apenas porque sabia que estaria atualizando em massa após a criação inicial dos dados, ou seja, a coluna não ficaria vazia por muito tempo.

TÃO GRANDE CAVEAT AQUI: Esta não é uma solução particularmente eficiente, mas é útil no caso em que você está reunindo um conjunto de dados, por exemplo, para solicitações pontuais de inteligência em que está criando uma tabela para mineração de dados, aplicando algum processamento / interpretação em massa e armazenar antes e depois dos resultados para posterior comparação / mineração. Esta é uma ocorrência frequente na minha linha de trabalho.

Você pode preencher inicialmente usando a palavra-chave SPACE, ou seja,

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

Atualizações subsequentes para "nome_da_coluna" de 10 caracteres ou menos (substitua conforme aplicável) serão permitidas sem causar erro truncado. Novamente, eu usaria isso apenas em cenários semelhantes aos descritos na minha ressalva.


1

Criei um procedimento armazenado que analisa uma tabela ou consulta de origem com várias características por coluna, entre as quais o comprimento mínimo (min_len) e o comprimento máximo (max_len).

CREATE PROCEDURE [dbo].[sp_analysetable] (
  @tableName varchar(8000),
  @deep bit = 0
) AS

/*
sp_analysetable 'company'
sp_analysetable 'select * from company where name is not null'
*/

DECLARE @intErrorCode INT, @errorMSG VARCHAR(500), @tmpQ NVARCHAR(2000), @column_name VARCHAR(50), @isQuery bit
SET @intErrorCode=0

IF OBJECT_ID('tempdb..##tmpTableToAnalyse') IS NOT NULL BEGIN
  DROP TABLE ##tmpTableToAnalyse
END
IF OBJECT_ID('tempdb..##tmpColumns') IS NOT NULL BEGIN
  DROP TABLE ##tmpColumns
END

if CHARINDEX('from', @tableName)>0
  set @isQuery=1

IF @intErrorCode=0 BEGIN
  if @isQuery=1 begin
    --set @tableName = 'USE '+@db+';'+replace(@tableName, 'from', 'into ##tmpTableToAnalyse from')
    --replace only first occurance. Now multiple froms may exists, but first from will be replaced with into .. from
    set @tableName=Stuff(@tableName, CharIndex('from', @tableName), Len('from'), 'into ##tmpTableToAnalyse from')
    exec(@tableName)
    IF OBJECT_ID('tempdb..##tmpTableToAnalyse') IS NULL BEGIN
      set @intErrorCode=1
      SET @errorMSG='Error generating temporary table from query.'
    end
    else begin
      set @tableName='##tmpTableToAnalyse'
    end
  end
end

IF @intErrorCode=0 BEGIN
  SET @tmpQ='USE '+DB_NAME()+';'+CHAR(13)+CHAR(10)+'
  select
    c.column_name as [column],
    cast(sp.value as varchar(1000)) as description,
    tc_fk.constraint_type,
    kcu_pk.table_name as fk_table,
    kcu_pk.column_name as fk_column,
    c.ordinal_position as pos,
    c.column_default as [default],
    c.is_nullable as [null],
    c.data_type,
    c.character_maximum_length as length,
    c.numeric_precision as [precision],
    c.numeric_precision_radix as radix,
    cast(null as bit) as [is_unique],
    cast(null as int) as min_len,
    cast(null as int) as max_len,
    cast(null as int) as nulls,
    cast(null as int) as blanks,
    cast(null as int) as numerics,
    cast(null as int) as distincts,
    cast(null as varchar(500)) as distinct_values,
    cast(null as varchar(50)) as remarks
  into ##tmpColumns'
  if @isQuery=1 begin
    SET @tmpQ=@tmpQ+' from tempdb.information_schema.columns c, (select null as value) sp'
  end
  else begin
    SET @tmpQ=@tmpQ+'
      from information_schema.columns c
      left join sysobjects so    on so.name=c.table_name  and so.xtype=''U''
      left join syscolumns sc    on sc.name=c.column_name and sc.id  =so.id 
      left join sys.extended_properties sp on sp.minor_id = sc.colid AND sp.major_id = sc.id and sp.name=''MS_Description''  
      left join information_schema.key_column_usage kcu_fk    on kcu_fk.table_name = c.table_name     and c.column_name = kcu_fk.column_name
      left join information_schema.table_constraints tc_fk    on kcu_fk.table_name = tc_fk.table_name and kcu_fk.constraint_name = tc_fk.constraint_name
      left join information_schema.referential_constraints rc on rc.constraint_name = kcu_fk.constraint_name
      left join information_schema.table_constraints tc_pk    on rc.unique_constraint_name = tc_pk.constraint_name
      left join information_schema.key_column_usage kcu_pk    on tc_pk.constraint_name = kcu_pk.constraint_name
 '
  end
  SET @tmpQ=@tmpQ+' where c.table_name = '''+@tableName+''''

  exec(@tmpQ)
end

IF @intErrorCode=0 AND @deep = 1 BEGIN
  DECLARE
    @count_rows int,
    @count_distinct int,
    @count_nulls int,
    @count_blanks int,
    @count_numerics int,
    @min_len int,
    @max_len int,
    @distinct_values varchar(500)
  DECLARE curTmp CURSOR LOCAL FAST_FORWARD FOR
    select [column] from ##tmpColumns;
  OPEN curTmp
  FETCH NEXT FROM curTmp INTO @column_name
  WHILE @@FETCH_STATUS = 0 and @intErrorCode=0 BEGIN
    set @tmpQ = 'USE '+DB_NAME()+'; SELECT'+
      '  @count_rows=count(0), '+char(13)+char(10)+
      '  @count_distinct=count(distinct ['+@column_name+']),'+char(13)+char(10)+
      '  @count_nulls=sum(case when ['+@column_name+'] is null then 1 else 0 end),'+char(13)+char(10)+
      '  @count_blanks=sum(case when ltrim(['+@column_name+'])='''' then 1 else 0 end),'+char(13)+char(10)+
      '  @count_numerics=sum(isnumeric(['+@column_name+'])),'+char(13)+char(10)+
      '  @min_len=min(len(['+@column_name+'])),'+char(13)+char(10)+
      '  @max_len=max(len(['+@column_name+']))'+char(13)+char(10)+
      ' from ['+@tableName+']'
    exec sp_executesql @tmpQ,
                       N'@count_rows int OUTPUT,
                         @count_distinct int OUTPUT,
                         @count_nulls int OUTPUT,
                         @count_blanks int OUTPUT,
                         @count_numerics int OUTPUT,
                         @min_len int OUTPUT,
                         @max_len int OUTPUT',
                       @count_rows     OUTPUT,
                       @count_distinct OUTPUT,
                       @count_nulls    OUTPUT,
                       @count_blanks    OUTPUT,
                       @count_numerics OUTPUT,
                       @min_len        OUTPUT,
                       @max_len        OUTPUT

    IF (@count_distinct>10) BEGIN
      SET @distinct_values='Many ('+cast(@count_distinct as varchar)+')'
    END ELSE BEGIN
      set @distinct_values=null
      set @tmpQ = N'USE '+DB_NAME()+';'+
        '  select @distinct_values=COALESCE(@distinct_values+'',''+cast(['+@column_name+'] as varchar),  cast(['+@column_name+'] as varchar))'+char(13)+char(10)+
        '  from ('+char(13)+char(10)+
        '    select distinct ['+@column_name+'] from ['+@tableName+'] where ['+@column_name+'] is not null) a'+char(13)+char(10)
      exec sp_executesql @tmpQ,
                         N'@distinct_values varchar(500) OUTPUT',
                         @distinct_values        OUTPUT
    END
    UPDATE ##tmpColumns SET
      is_unique      =case when @count_rows=@count_distinct then 1 else 0 end,
      distincts      =@count_distinct,
      nulls          =@count_nulls,
      blanks         =@count_blanks,
      numerics       =@count_numerics,
      min_len        =@min_len,
      max_len        =@max_len,
      distinct_values=@distinct_values,
      remarks       =
        case when @count_rows=@count_nulls then 'all null,' else '' end+
        case when @count_rows=@count_distinct then 'unique,' else '' end+
        case when @count_distinct=0 then 'empty,' else '' end+
        case when @min_len=@max_len then 'same length,' else '' end+
        case when @count_rows=@count_numerics then 'all numeric,' else '' end
    WHERE [column]=@column_name

    FETCH NEXT FROM curTmp INTO @column_name
  END
  CLOSE curTmp DEALLOCATE curTmp
END

IF @intErrorCode=0 BEGIN
  select * from ##tmpColumns order by pos
end

IF @intErrorCode=0 BEGIN --Clean up temporary tables
  IF OBJECT_ID('tempdb..##tmpTableToAnalyse') IS NOT NULL BEGIN
    DROP TABLE ##tmpTableToAnalyse
  END
  IF OBJECT_ID('tempdb..##tmpColumns') IS NOT NULL BEGIN
    DROP TABLE ##tmpColumns
  END
end

IF @intErrorCode<>0 BEGIN
  RAISERROR(@errorMSG, 12, 1)
END
RETURN @intErrorCode

Eu armazeno esse procedimento no banco de dados mestre para poder usá-lo em todos os bancos de dados da seguinte forma:

sp_analysetable 'table_name', 1
// deep=1 for doing value analyses

E a saída é:

column description constraint_type fk_table fk_column pos default null data_type length precision radix is_unique min_len max_len nulls blanks numerics distincts distinct_values remarks
id_individual NULL PRIMARY KEY NULL NULL 1 NULL NO int NULL 10 10 1 1 2 0 0 70 70 Many (70) unique,all numeric,
id_brand NULL NULL NULL NULL 2 NULL NO int NULL 10 10 0 1 1 0 0 70 2 2,3 same length,all numeric, guid NULL NULL NULL NULL 3 (newid()) NO uniqueidentifier NULL NULL NULL 1 36 36 0 0 0 70 Many (70) unique,same length,
customer_id NULL NULL NULL NULL 4 NULL YES varchar 50 NULL NULL 0 NULL NULL 70 0 0 0 NULL all null,empty,
email NULL NULL NULL NULL 5 NULL YES varchar 100 NULL NULL 0 4 36 0 0 0 31 Many (31)
mobile NULL NULL NULL NULL 6 NULL YES varchar 50 NULL NULL 0 NULL NULL 70 0 0 0 NULL all null,empty,
initials NULL NULL NULL NULL 7 NULL YES varchar 50 NULL NULL 0 NULL NULL 70 0 0 0 NULL all null,empty,
title_short NULL NULL NULL NULL 8 NULL YES varchar 50 NULL NULL 0 NULL NULL 70 0 0 0 NULL all null,empty,
title_long NULL NULL NULL NULL 9 NULL YES varchar 50 NULL NULL 0 NULL NULL 70 0 0 0 NULL all null,empty,
firstname NULL NULL NULL NULL 10 NULL YES varchar 50 NULL NULL 0 NULL NULL 70 0 0 0 NULL all null,empty,
lastname NULL NULL NULL NULL 11 NULL YES varchar 50 NULL NULL 0 NULL NULL 70 0 0 0 NULL all null,empty,
address NULL NULL NULL NULL 12 NULL YES varchar 100 NULL NULL 0 NULL NULL 70 0 0 0 NULL all null,empty,
pc NULL NULL NULL NULL 13 NULL YES varchar 10 NULL NULL 0 NULL NULL 70 0 0 0 NULL all null,empty,
kixcode NULL NULL NULL NULL 14 NULL YES varchar 20 NULL NULL 0 NULL NULL 70 0 0 0 NULL all null,empty,
date_created NULL NULL NULL NULL 15 (getdate()) NO datetime NULL NULL NULL 1 19 19 0 0 0 70 Many (70) unique,same length,
created_by NULL NULL NULL NULL 16 (user_name()) NO varchar 50 NULL NULL 0 13 13 0 0 0 1 loyalz-public same length,
id_location_created NULL FOREIGN KEY location id_location 17 NULL YES int NULL 10 10 0 1 1 0 0 70 2 1,2 same length,all numeric, id_individual_type NULL FOREIGN KEY individual_type id_individual_type 18 NULL YES int NULL 10 10 0 NULL NULL 70 0 0 0 NULL all null,empty,
optin NULL NULL NULL NULL 19 NULL YES int NULL 10 10 0 1 1 39 0 31 2 0,1 same length,


Nota lateral: você não deve usar o sp_prefixo para seus procedimentos armazenados. A Microsoft reservou esse prefixo para seu próprio uso (consulte Naming Stored Procedures ) e você corre o risco de um conflito de nome em algum momento no futuro. Também é ruim para o desempenho do procedimento armazenado . É melhor simplesmente evitar sp_e usar outra coisa como prefixo - ou nenhum prefixo!
Marc #

1

Eu escrevi um procedimento útil de armazenamento para ajudar a identificar e resolver o problema de truncamento de texto (dados binários ou de seqüência de caracteres seriam truncados) quando a instrução INSERT SELECT é usada. Ele compara apenas os campos CHAR, VARCHAR, NCHAR E NVARCHAR e retorna um campo de avaliação por campo, no caso de ser a possível causa do erro.

EXEC dbo.GetFieldStringTruncate SourceTableName, TargetTableName

Este procedimento armazenado é orientado para o problema de truncamento de texto quando uma instrução INSERT SELECT é feita.

A operação deste procedimento armazenado depende de o usuário identificar previamente a instrução INSERT com o problema. Em seguida, insira os dados de origem em uma tabela temporária global. A instrução SELECT INTO é recomendada.

Você deve usar o mesmo nome do campo da tabela de destino no alias de cada campo da instrução SELECT.

CÓDIGO DE FUNÇÃO:

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, '')


        --/programming/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

Por enquanto, suporta apenas os tipos de dados CHAR, VARCHAR, NCHAR e NVARCHAR . Você pode encontrar a última versão deste código no próximo link abaixo e nos ajudamos a melhorá-lo. GetFieldStringTruncate.sql

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


1

Se você estiver no SQL Server 2016-2017: para corrigi-lo, ative o sinalizador de rastreamento 460

DBCC TRACEON(460, 1);
GO

e desative-o depois de:

DBCC TRACEOFF(460, 1);
GO

fonte


0

isso também pode acontecer quando você não tem permissões adequadas


2
Realmente? Um erro real 'String ou dados binários seria truncado'? Parece um erro muito estranho se você não tiver permissões. Existe uma permissão que impede você de escrever mais do que uma certa quantidade de dados? (Eu estou interessado, porque eu quero verificar se o tamanho do campo automaticamente quando eu recebo este erro - por isso, se ela pode ocorrer por alguma outra razão que é muito interessante)
Ian Grainger

0

Eu tive uma questão semelhante. Eu estava copiando dados de uma tabela para uma tabela idêntica em tudo, menos no nome.

Eventualmente, eu joguei a tabela de origem em uma tabela temporária usando uma instrução SELECT INTO.

SELECT *
INTO TEMP_TABLE
FROM SOURCE_TABLE;

Comparei o esquema da tabela de origem à tabela temporária. Eu descobri que uma das colunas era varchar(4000)quando eu esperava varchar(250).

ATUALIZAÇÃO: A questão do varchar (4000) pode ser explicada aqui caso você esteja interessado:

Para Nvarchar (Max), estou recebendo apenas 4000 caracteres no TSQL?

Espero que isto ajude.


0

Este erro é gerado quando a coluna de uma tabela coloca restrição [principalmente comprimento]. . Por exemplo, se o esquema do banco de dados para a coluna myColumn for CHAR (2), quando sua chamada de qualquer aplicativo para inserir valor, você deve passar a String de comprimento dois.

O erro basicamente diz isso; A sequência de comprimento três e superior é inconsistente para ajustar-se à restrição de comprimento especificada pelo esquema do banco de dados. É por isso que o SQL Server avisa e lança erro de perda / truncamento de dados.


0

Por favor, tente o seguinte código:

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]
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.