2016-11-19 88 views
0

我插入数据从一个表到另一个,新的表结构主要是从旧表与几个新的列,当我运行我的查询我得到的错误:从一个表插入数据到另一个数据将被截断

String or binary data would be truncated.

我插入查询中的值来自一个SELECT语句返回70000行,所以我不知道如何找出什么样的数据导致了错误,有没有办法找出?

+0

上有SO一些其它问题:http://stackoverflow.com/questions/6388756/sql-server-string-or-binary-data-would -be截断。你也可以看看这里:http://blogs.lessthandot.com/index。php/datamgmt/datadesign/how-to-find-what-c​​olumn/ – Klinger

回答

0

这是一个轻量级的检查(仅元数据),以缩小搜索到可能导致问题的列的列表 -
列其中靶表中的MAX_LENGTH比越小匹配的MAX_LENGTH源查询中的表达式。


创建基于源查询结果为空表和比较的元数据。

实施例:

create table src (str1 varchar(11),str2 varchar(3)); 
create table trg (str1 varchar(7),str2 varchar(3));  
insert into src values ('Hi','XY'),('Hello world','XY'),('Hi','XYZ') 

insert into trg (str1,str2) select str1,str2 + 'D' from src 

Msg 8152, Level 16, State 14, Line 10
String or binary data would betruncated.

select str1,str2+'D' as str2 into tmp from src where 1=2; 

select  * 

from  (select  c.name 
         ,min(case o.name when 'tmp' then t.name end)   as tmp_type 
         ,min(case o.name when 'trg' then t.name end)   as trg_type 
         ,min(case o.name when 'tmp' then c.max_length end) as tmp_max_length 
         ,min(case o.name when 'trg' then c.max_length end) as trg_max_length 

      from     sys.objects as o 
         join  sys.columns as c 
         on   c.object_id   = o.object_id 
         join  sys.types as t 
         on   t.system_type_id = c.system_type_id 
           and t.user_type_id  = c.user_type_id 

      where  o.name in ('tmp','trg') 
        and ( c.collation_name is not null 
         or c.name in ('binary','varbinary') 
         ) 

      group by c.name 
      ) c 

where  tmp_max_length > trg_max_length 

order by c.name 
; 

+------+----------+----------+----------------+----------------+ 
| name | tmp_type | trg_type | tmp_max_length | trg_max_length | 
+------+----------+----------+----------------+----------------+ 
| str1 | varchar | varchar | 11    | 7    | 
+------+----------+----------+----------------+----------------+ 
| str2 | varchar | varchar | 4    | 3    | 
+------+----------+----------+----------------+----------------+ 
2

目标表中的一个或多个列的类型不是足以包含来自源表的数据,源表列中的数据比其中的数据更宽目标列可以包含。

例如源表有一栏XNVARCHAR(200)类型和你想的是复制到目标表列YNVARCHAR(100)类型。源表中至少有一行,其值为X,宽度大于100个字符。复制该列会丢失数据,并且会导致出现相同的错误。


你需要做的是两种:

  • 更改目标表是不够宽
  • 要明确,如果数据丢失的目的,并使用CAST明确地类型的列。例如我之前给出的例子,CAST(X AS VARCHAR(100))

实施例:

DECLARE @s TABLE(x NVARCHAR(20)); 
INSERT INTO @s(x)VALUES(N'123456789'); -- data in source column wider than what the target column can contain 

DECLARE @t TABLE(y NVARCHAR(10)); -- target column is less wide than source column 

INSERT INTO @t(y) SELECT x FROM @s; -- this statement will fail with the same error as you have 

INSERT INTO @t(y) SELECT CAST(x AS NVARCHAR(10)) FROM @s; -- this statement succeeds, only use if data loss is intended 
+0

这不回答OP问题。他不是问为什么他得到这个错误,而是如何找到导致这个错误的数据。 –

+0

@DuduMarkovitz我要说的是,他不应该首先寻找导致错误的数据。他应该改变自己的工作方式:或者让目标表的列至少与源文件一样宽,或者在数据丢失的情况下进行明确的转换。因为一旦他运行一个脚本来找到罪魁祸首的列/数据,他会做什么? –

+0

@DuduMarkovitz虽然=)不要误解我的意思,但你确实有一点。但是你的答案是“找出导致错误的数据”*? –

相关问题