Jim*_*ans 132 t-sql sql-server migration data-migration sql-server-2005
我参与了一个数据迁移项目.当我尝试将数据从一个表插入另一个表(SQL Server 2005)时,我收到以下错误:
消息8152,级别16,状态13,行1
字符串或二进制数据将被截断.
源数据列与数据类型匹配,并且在目标表列的长度定义内,因此我不知道可能导致此错误的原因.
IAm*_*rey 171
您需要发布源表和目标表的表定义,以便我们找出问题所在,但最重要的是源表中的一个列大于目标列.可能是您正在以您不知道的方式更改格式.您正在迁移的数据库模型对于确定这一点非常重要.
Rud*_*haw 67
正如其他人已经说过的那样,源表中的一个列数据类型大于目标列.
因为这里没有人提到它,一个简单的解决方案(类似于托马斯的__CODE__
解决方案)就是简单地关闭警告并允许截断.因此,如果您收到此错误但是您确定可以接受旧数据库/表中的数据被截断(按尺寸切割),则可以执行以下操作:
SET ANSI_WARNINGS OFF;
-- Your insert TSQL here.
SET ANSI_WARNINGS ON;
Run Code Online (Sandbox Code Playgroud)
如上所述,请务必记住之后再次打开警告.我希望这有帮助.
Tho*_*mas 59
问题非常简单:源查询中的一个或多个列包含的数据超出了其目标列的长度.一个简单的解决方案是获取源查询并Max(Len( source col ))
在每列上执行.也就是说,
Select Max(Len(TextCol1))
, Max(Len(TextCol2))
, Max(Len(TextCol3))
, ...
From ...
Run Code Online (Sandbox Code Playgroud)
然后将这些长度与目标表中的数据类型长度进行比较.至少一个超过其目标列长度.
如果你绝对肯定这不应该是这种情况并且不关心它是不是这种情况,那么另一个解决方案是强制将源查询列强制转换为它们的目标长度(这会截断任何太长的数据):
Select Cast(TextCol1 As varchar(...))
, Cast(TextCol2 As varchar(...))
, Cast(TextCol3 As varchar(...))
, ...
From ...
Run Code Online (Sandbox Code Playgroud)
SQL Server 2019最终将返回更有意义的错误消息。
如果您在生产中遇到该错误,则看不到该错误来自哪一列或哪一行,以及如何精确定位。
要启用新行为,您需要使用DBCC TRACEON(460)
。来自的新错误文本sys.messages
:
SELECT * FROM sys.messages WHERE message_id = 2628
Run Code Online (Sandbox Code Playgroud)
2628 –表'%。* ls'的列'%。* ls'中的字符串或二进制数据将被截断。截断的值:'%。* ls'。
此新消息还被反向移植到SQL Server 2017 CU12(以及即将发布的SQL Server 2016 SP2 CU),但默认情况下不是。您需要启用跟踪标志460,以在会话或服务器级别用2628替换消息ID 8152。
请注意,目前,即使在SQL Server 2019 CTP 2.0中,也需要启用相同的跟踪标志460。在将来的SQL Server 2019版本中,默认情况下,消息2628将替换消息8152。
SQL Server 2017 CU12也支持此功能。
改进:在SQL Server 2017中带有扩展信息的“字符串或二进制数据将被截断”消息的可选替换
此SQL Server 2017更新引入了包含以下附加上下文信息的可选消息。
Run Code Online (Sandbox Code Playgroud)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'.
新消息ID为2628。如果启用了跟踪标志460,此消息将替换任何错误输出中的消息8152。
小智 7
另一个可能的原因是,如果您为超出列长度的列设置了默认值.看起来有人胖了一根长度为5的列,但是默认值超过了5的长度.这让我疯狂,因为我试图理解为什么它不能用于任何插入,即使我插入的是一个整数为1的单个列.因为表模式上的默认值违反了默认值,所以它全部搞砸了 - 我想我们学到了这一点 - 避免在模式中使用默认值的表.:)
我将添加导致此错误的另一个可能原因,只是因为没有人提到它,并且它可能会帮助未来的某个人(因为OP已经找到了他的答案)。如果您要插入的表有触发器,则可能是触发器正在生成错误。我见过这种情况发生在表字段定义更改时,但审计表没有更改时。
小智 6
如果您\xe2\x80\x99 在 SQL Server 2016-2017 上:\n要修复它,请打开跟踪标志 460
\n\nDBCC TRACEON(460, 1);\nGO\n
Run Code Online (Sandbox Code Playgroud)\n\n并确保在以下情况后将其关闭:
\n\nDBCC TRACEOFF(460, 1);\nGO\n
Run Code Online (Sandbox Code Playgroud)\n\n\n