【问题标题】:Msg 8152, Level 16, State 14, Line XXX String or binary data would be truncate消息 8152,级别 16,状态 14,行 XXX 字符串或二进制数据将被截断
【发布时间】:2014-11-06 23:10:50
【问题描述】:

场景:一个大型存储过程每天运行数千次,每年每周运行 6 天。对于这种特定情况,我遇到了错误

消息 8152,第 16 层,第 14 州,第 114 行
字符串或二进制数据将被截断

这个存储过程大约有 800 行代码,有很多参数、很多变量和很多表。

Go
@exampleParam varchar(30) 
@exampleParam datetime
DECLARE @declaredvara VARCHAR(50);
DECLARE @declaredvarb VARCHAR(50);  -- where the line error is according to the printout
DECLARE @declaredvarc VARCHAR(50);
DECLARE @declaredvard VARCHAR(50);  -- where line error is adjusted for comments in front of GO
BEGIN TRANS
-- some calculations (700+ lines)
COMMIT TRANS
--error catch
ROLLBACK TRANS

问题:我想知道是否可以读取准确的 Line 错误,因此我至少可以缩小我必须检查的表的范围。这个存储过程涉及大量的表。

*** 它所指向的两个声明变量(GO 调整前后)都是自重,它们是 nvr 使用的。

奖励信息:我运行存储过程时填充了参数和参数 = '',日期时间除外。在这两种情况下,我都遇到了同样的错误。但是,我知道存储过程可以正常工作,因为它每天被使用数千次而没有出现此错误。

EXEC SP '','','','','2014-11-6'
EXEC SP 'XX_XX_XX','',1,'','2014-11-6'
--both return the same error of Msg 8152, Level 16, State 14
--XX is a specific serialnum.  
--However all other serialnum have no problem

编辑:数据库正在运行 SQL Server 2005 EDIT2:我正在使用 SQL Server 2008 进行编辑。 - 所以调试不是一种选择

【问题讨论】:

  • 您是否将 @declaredvarb 作为 varchar(50) 与其等效的 sql server 表进行了比较?您在某处将 1.) 超过 50 个字符放入变量中,2.) 列架构比您的数据更窄(字符串大于您的列)或 3. 将 Unicode 数据放入 varchar 字段中。
  • 行号只会告诉你从批处理开始的行数,所以如果你有一个GO(或者如果你重新定义了你的批处理分隔符),它就是从那里开始的行数。
  • 双击 SSMS 中的错误消息,它应该可以了解错误行的位置。
  • @paqogomez 甚至没有使用行错误指向的变量。它刚刚声明,在评论它们时,会发生同样的错误。
  • @DavidG 我在 AlterProcedure 之前调整了 GO 的计数。无论哪种情况,它们都指向未使用的已声明变量。

标签: sql sql-server tsql stored-procedures


【解决方案1】:

用于修复 Msg 8152, Level 16, State 14, Line 114 字符串或二进制数据将被截断。

SET ansi_warnings OFF
GO

【讨论】:

  • 虽然您在此处的回答可能不是最佳实践,但在某些情况下可以解决问题。 &在我的情况下,它非常完美,因为我不太担心我可能会在截断中丢失什么,但它是一个正确的 PITA 来确定 20 个左右的字段中的哪个字段没有正确排列...... THX!
【解决方案2】:
BEGIN CATCH    
 DECLARE @body VARCHAR(4000)    
 SET @body='<b>Exception in spname   </b><br/>'    
 SET @body=@body + ( SELECT        
 '<b>Error No :</b> '+ CONVERT(VARCHAR(100),ERROR_NUMBER()) +'<br/>'    
  +'<b>Error Severity :</b> '+CONVERT(VARCHAR(1000),ERROR_SEVERITY()) +'<br/>'    
  +'<b>Error State :</b> '+CONVERT(VARCHAR(1000),ERROR_STATE()) + '<br/>'    
  +'<b>Error Procedure :</b> '+CONVERT(VARCHAR(1000),ERROR_PROCEDURE())+'<br/>'    
  +'<b>Error Line :</b> '+CONVERT(VARCHAR(100),ERROR_LINE())+'<br/>'    
  +'<b>Error Message :</b> '+CONVERT(VARCHAR(2000),ERROR_MESSAGE()));    

END CATCH 

【讨论】:

  • 我不经常使用 TRY CATCH(坏习惯?我猜我还是个新手)但是你不需要 PRINT cmd 来查看错误吗?
【解决方案3】:

这个错误表明你要存储一些比它的存储更大的东西。您可能需要检查是否要在 @declaredvara 或 @declaredvarb 或 @declaredvarc 或 @declaredvard 或任何其他变量或表列中存储超过 50 个字符的字符串。例如,您可以将 @test 定义为 varchar(2),然后尝试将 'vahid' 插入其中。在这种情况下,将抛出类似的异常。有两种方法(据我所知)可以找到错误发生行:

  1. 如果您需要找到确切的错误发生行,您可能需要使用 sql server 调试工具调试您的 SP(阅读有关在 Sql Server 中调试的更多信息here
  2. 您还可以使用 TRY...CATCH 块来检查 SP 中的哪个代码块导致了错误。

【讨论】:

  • 不幸的是,数据库是 SQL Server 2005,但我拥有的编辑软件是 2008,因此无法选择调试。
【解决方案4】:

原来该区域中的一个变量已声明但从未给出值。

该变量后来被用作从内部执行另一个存储过程的参数。 这导致一个空参数被传递到一个不能包含它的参数中。

感谢大家的回复。

【讨论】:

    猜你喜欢
    • 2021-02-03
    • 1970-01-01
    • 2019-11-11
    • 1970-01-01
    • 1970-01-01
    • 2014-06-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多