有没有什么好方法可以调试“字符串或二进制数据会被截断?”

时间:2010-07-14 17:12:41

标签: sql-server-2008

这一年是2010年。

SQL Server许可证并不便宜。

然而,此错误仍未指示 产生问题的 。好吧,它甚至不能告诉你它是“字符串”还是“二进制”数据。

我错过了什么吗?

10 个答案:

答案 0 :(得分:17)

解决这些问题的快捷方法是将行选择到新的物理表中,如下所示:

SELECT * INTO dbo.MyNewTable FROM <the rest of the offending query goes here>

...然后将此表的模式与INSERT先前进入的表的模式进行比较 - 并查找更大的列。

答案 1 :(得分:2)

我意识到这是一个旧的。这是我使用的一小段代码有帮助。

这样做会返回您尝试从中选择的表中的最大长度表。然后,您可以将字段长度与每列返回的最大值进行比较,并找出导致问题的最大值。然后,它只是一个简单的查询来清理数据或将其排除。

DECLARE @col NVARCHAR(50)
DECLARE @sql NVARCHAR(MAX);

CREATE TABLE ##temp (colname nvarchar(50), maxVal int)

DECLARE oloop CURSOR FOR

SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'SOURCETABLENAME' AND TABLE_SCHEMA='dbo'

OPEN oLoop 

   FETCH NEXT FROM oloop INTO @col;

   WHILE (@@FETCH_STATUS = 0)
   BEGIN
      SET @sql = '
   DECLARE @val INT;
   SELECT @val = MAX(LEN(' + @col + ')) FROM dbo.SOURCETABLENAME;
   INSERT INTO ##temp
           ( colname, maxVal )
   VALUES  ( N''' + @col + ''', -- colname - nvarchar(50)
             @val  -- maxVal - int
             )';
      EXEC(@sql);
      FETCH NEXT FROM oloop INTO @col;
   END

   CLOSE oloop;
   DEALLOCATE oloop

   SELECT * FROM ##temp
   DROP TABLE ##temp;

答案 2 :(得分:2)

这里的另一种方法是使用二进制搜索。

注释代码中的一半列,然后重试。如果错误仍然存​​在,请注释掉该半部分的另一半并再试一次。您最终会将搜索范围缩小到两列。

答案 3 :(得分:1)

您可以使用if条件检查每个插入值的长度,如果值需要的宽度大于当前列宽,则截断该值并抛出自定义错误。

如果您只需要确定哪个是导致问题的字段,这应该可行。我不知道有没有更好的方法来做到这一点。

答案 4 :(得分:1)

建议您投票支持Microsoft网站上的增强请求。它已经活跃了6年了,所以谁知道微软是否会做任何事情,但至少你可以成为一个吱吱作响的轮子:Microsoft Connect

答案 5 :(得分:1)

对于字符串截断,我想出了以下解决方案来查找所有列的最大长度:

1)选择临时表的所有数据(在需要时提供列名称),例如

SELECT  col1
       ,col2
       ,col3_4 = col3 + '-' + col4
INTO   #temp;

2)在同一连接中运行以下SQL语句(如果需要,调整临时表名):

DECLARE @table  VARCHAR(MAX) = '#temp';      -- change this to your temp table name

DECLARE @select VARCHAR(MAX) = '';
DECLARE @prefix VARCHAR(256) = 'MAX(LEN(';
DECLARE @suffix VARCHAR(256) = ')) AS max_';
DECLARE @nl     CHAR(2)      = CHAR(13) + CHAR(10);

SELECT  @select = @select + @prefix + name + @suffix + name + @nl + ','
FROM    tempdb.sys.columns 
WHERE   object_id = object_id('tempdb..' + @table);

SELECT  @select = 'SELECT ' + @select + '0' + @nl + 'FROM ' + @table

EXEC(@select);

它将返回一个结果集,其列名前缀为&#39; max _&#39;并显示每列的最大长度。

识别出错列后,您可以运行其他select语句来查找超长行并根据需要调整代码/数据。

答案 6 :(得分:0)

我真的想不出一个好方法。
我曾经花了很多时间调试一个非常有用的“分零”信息。

通常你会注释掉各种输出代码,以找出引起问题的输出代码 然后你拿这个你找到的那个并让它返回一个值,表示存在问题而不是实际值(在你的情况下,应该用len(of the output)替换字符串输出)。然后手动比较要插入的列的长度。

答案 7 :(得分:0)

从错误消息中的行号,您应该能够识别导致错误的插入查询。将其修改为select查询,以便在查询中包含AND LEN(your_expression_or_column_here) > CONSTANT_COL_INT_LEN字符串的各个列。看看输出,它会给你不好的行。

答案 8 :(得分:0)

从技术上讲,没有一行要指向,因为SQL没有将数据写入表中。我通常只是捕获跟踪,运行它查询分析器(除非问题已经从跟踪中显而易见,在这种情况下可能是这样),并从那里快速调试与旧的“修改我的UPDATE到SELECT”方法。它不是真的只分解为两件事之一:

a)您的列定义错误,需要更改宽度 b)您的列定义是正确的,应用程序需要更具防御性

答案 9 :(得分:0)

对我有用的最好的事情是使用select .... into #temptable将行首先放入临时表中 然后我获取了临时表中每列的最大长度。例如。选择max(len(jobid))作为Jobid,.... 然后将其与源表字段定义进行比较。