SQL Serverstring或二进制数据将被截断
我参与了数据迁移项目。 当我尝试从一个表插入数据到另一个表(SQL Server 2005)时出现以下错误:
Msg 8152,Level 16,State 13,Line 1
string或二进制数据将被截断。
源数据列匹配数据types,并在目标表列的长度定义内,所以我不知道是什么原因导致了这个错误。
您需要发布源表和目标表的表格定义,以便我们找出问题所在,但底线是源表中的某一列比您的目标列更大 。 这可能是因为你正在改变你不知道的方式。 你正在从中移动的数据库模型也很重要。
问题很简单:源查询中的一个或多个列包含的数据超出了其目标列的长度。 一个简单的解决办法是采取您的源查询和每列执行Max(Len( source col ))
。 也就是说,
Select Max(Len(TextCol1)) , Max(Len(TextCol2)) , Max(Len(TextCol3)) , ... From ...
然后将这些长度与目标表中的数据types长度进行比较。 至less有一个超出了目标列的长度。
如果你绝对肯定这不应该是这种情况,并不在乎如果不是这种情况 ,那么另一种解决scheme是强制性地将源查询列转换为目标长度(这会截断任何太长的数据):
Select Cast(TextCol1 As varchar(...)) , Cast(TextCol2 As varchar(...)) , Cast(TextCol3 As varchar(...)) , ... From ...
正如其他人已经说过,源表中的一个列数据types比您的目标列大。
由于没有人在这里提到过,所以简单的解决scheme(类似于Thomas的CAST
解决scheme)就是简单地closures警告并允许截断发生。 所以,如果你收到这个错误,但是你确定旧数据库/表中的数据被截断(缩小),你可以简单地执行以下操作:
SET ANSI_WARNINGS OFF; -- Your insert TSQL here. SET ANSI_WARNINGS ON;
如上所述,请务必记得在之后再次发出警告。 我希望这有帮助。
另外一个可能的原因是,如果您的列的默认值设置超出了列的长度。 它似乎有人发了一个长度为5的列,但默认值超过了5的长度。这使我疯狂,因为我试图了解为什么它不工作的任何插入,即使我插入的是一个整数为1的列。由于表模式的默认值违反了默认值,所以它将所有这一切都搞砸了 – 我猜测我们已经把这些经验教训带到了我们的教训 – 避免在模式中使用默认值的表。 🙂
这可能是个具有挑战性的错误。 以下是从https://connect.microsoft.com/SQLServer/feedback/details/339410/中查找AmirCharania的注释。;
我已经调整了由AmirCharania给出的数据select到实际表中的答案,而不是一个临时的答案。 首先select你的数据集到一个开发表中,然后运行以下命令:
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)
是的,我也面临这样的问题。
REMARKS VARCHAR(500) to REMARKS VARCHAR(1000)
在这里,我把备忘录的长度从500改为1000
这也可能发生在你没有足够的权限时
对于其他人,也检查你的存储过程 。 在我的情况下,在我的存储过程CustomSearch
我不小心宣布了我的专栏没有足够的长度,所以当我input一个大数据我收到错误,即使我有一个很大的长度在我的数据库。 我只是在自定义search中更改了列的长度,错误消失了。 这只是为了提醒。 谢谢。
我今天遇到了这个问题,并在我search这个最小的信息错误消息的答案,我也发现这个链接:
所以看起来微软没有计划在不久的将来发布错误消息。
所以我转向其他手段。
我把错误复制到excel:
(1排受影响)
(1排受影响)
(1 row(s)affected)Msg 8152,Level 16,State 14,Line 13string或二进制数据将被截断。 声明已经终止。
(1排受影响)
计算在Excel中的行数,得到接近logging计数器,导致问题…调整我的出口代码打印出SQL接近它…然后运行5 – 10 SQL插入周围的问题SQL和设法找出问题之一,看到太长的string,增加该列的大小,然后大的导入文件没有任何问题。
一个黑客和一个解决方法的位,但是当你没有多lessselect离开时,你可以做任何事情。
我正在使用空string创build表,然后接收错误'消息8152,string或二进制数据将被截断'后续更新。 发生这种情况的原因是更新值包含6个字符,并且大于预期的列定义。 我使用“SPACE”来解决这个问题,只是因为我知道在初始数据创build之后我会进行批量更新,即列不会长时间保持空白。
如此大规模的解决scheme:这不是一个特别灵活的解决scheme,但在您将数据集合在一起的情况下非常有用,例如为您创build数据挖掘表的一次性智能请求,应用一些批量处理/解释存储结果之前和之后以供以后比较/挖掘。 这是我工作中经常发生的事情。
您最初可以使用SPACE关键字填充
select Table1.[column1] ,Table1.[column2] ,SPACE(10) as column_name into table_you_are_creating from Table1 where ...
然后将允许后续更新为10个字符或更less(替代适用)的“column_name”,而不会导致截断错误。 再一次,我只会在类似于我的警告中所描述的情况下使用它。
我build立了一个存储过程,它分析每个列中包含最小长度(min_len)和最大长度(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
我将这个过程存储在master数据库中,这样我就可以像这样在每个数据库中使用它:
sp_analysetable 'table_name', 1 // deep=1 for doing value analyses
输出是:
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,
我会添加一个其他可能的原因,因为没有人提到这个错误,这可能会帮助未来的人(因为OP已经find了答案)。 如果您插入的表具有触发器,则可能是触发器正在生成错误。 我已经看到这发生在表字段定义更改时,但审计表不是。
我有一个类似的问题。 我是从一个表复制数据到一个完全相同的表,而不是名字。
最后,我使用SELECT INTO语句将源表转储到临时表中。
SELECT * INTO TEMP_TABLE FROM SOURCE_TABLE;
我将源表的模式与临时表进行了比较。 当我期待一个varchar(250)
时,我发现其中一列是一个varchar(4000)
varchar(250)
。
更新:varchar(4000)问题可以在这里解释,如果你有兴趣:
对于Nvarchar(Max),我只能在TSQL中获得4000个字符?
希望这可以帮助。
CREATE TABLE [dbo]。[Department]([Department_name] char(10)NULL)
INSERT INTO [dbo]。部门VALUES('家庭医学') – 将发生错误
ALTER TABLE [部门] ALTER COLUMN [部门名称]字符(50)
INSERT INTO [dbo]。VALUES('Family Medicine')
从[部门]select*
当表的列放置约束[主要是长度]时引发此错误。 。 例如,如果列myColumn的数据库模式是CHAR(2),那么当你从你的任何应用程序中调用插入值时,你必须传递长度为2的string。
错误基本上说, 长度为3以上的string不一致以符合数据库模式指定的长度限制。 这就是为什么SQL Server警告并抛出数据丢失/截断错误。