SQL Server字符串二进制数据将被截断

SQL Server字符串二进制数据将被截断,sql,sql-server,sql-server-2008,Sql,Sql Server,Sql Server 2008,当更新一系列具有许多VarChar(n)列的表时,我执行替换操作的一些更新会使用“字符串或二进制数据将被截断”终止我的事务。我正在尝试想出一种可重复的方法来处理这个问题 一个选项是,如果要转换的列的长度超过该列的大小,则首先选择该列的行ID和长度。我不喜欢这一点,因为它看起来像是我不会得到任何查询计划的重用,而且执行起来很慢 另一个选项是找出如何捕获导致失败的行(第一行?),并将其报告给调用者。我认为这不会起作用,因为错误级别太高,无法让我确定问题所在 我也可以通过取新值的子字符串/左键并将其放

当更新一系列具有许多VarChar(n)列的表时,我执行替换操作的一些更新会使用“字符串或二进制数据将被截断”终止我的事务。我正在尝试想出一种可重复的方法来处理这个问题

一个选项是,如果要转换的列的长度超过该列的大小,则首先选择该列的行ID和长度。我不喜欢这一点,因为它看起来像是我不会得到任何查询计划的重用,而且执行起来很慢

另一个选项是找出如何捕获导致失败的行(第一行?),并将其报告给调用者。我认为这不会起作用,因为错误级别太高,无法让我确定问题所在

我也可以通过取新值的子字符串/左键并将其放入来忽略整个问题,但这会掩盖它,不会让我知道实际问题在哪里

我正在使用MSSQL 2008

编辑-这里的想法看起来很有希望: :


你从哪个来源更新?也就是说,您是作为基于集合的操作从另一个表进行更新,还是从应用程序中的循环进行更新,在应用程序中一次更新一行

这只是一个特定列的问题,还是您在不同列中遇到的问题

问题越有针对性,就越容易解决。回答这个问题,然后我会用更多信息更新我的答案。基本上,尽管您只想查询源数据中不会引起问题的记录并对其进行处理。然后将其余部分报告为异常和/或截断它们,以便在需要时导入它们

编辑:我不知道你想在什么样的环境中解决这个问题,但基本上你需要比较你要导入的数据的长度和它要导入的字段的长度。如果你用纯sql做这件事,那么很有可能做到,但这将是一个巨大的痛苦。如果你使用的是.net或类似的语言,那么应该不会有那么多麻烦

您的检查是在更新之前完成的,而不是作为更新的一部分。因此,查询计划的重用不是问题。如果速度是一个问题,那么你可能想想出一个策略,只有在你有一定数量的更新提交后才进行更新。通过这种方式,您可以执行基于集合的操作,例如一次更新100次,而不是一次更新1次。这假设你不需要实时更新

另一个选择是找出如何捕捉行(首先 行?)导致失败,并向来电者报告。我不认为 这将起作用,因为错误级别太高,我无法确定 这个问题。”

我认为您需要指出问题(即,问题发生在哪个列)。如果不是这样,那么您可以执行以下操作:

您可以尝试在启用ansi warnings的情况下进行更新,如果导致错误,则报告异常,关闭ansi warnings并将其导入表中,然后重新启用ansi warnings


但是如果你确实需要找出问题所在,那么需要更多的代码来定位问题。。。但是,为了提高速度,您可能不希望主动查找错误,因此您可以使用上述技术,并且只在sql告诉您存在错误时才查找问题。

我正在从任意字符串进行更新。数据是要发送到下游系统的报告输出,有些数据需要追加,就像在末尾追加文本“(已编辑)”。它在多个列中,我已经被困在做动态SQL以首先生成update语句中。那么每个字符串是否包含多个记录更新的数据,或者每个字符串只包含一个记录更新?还有一个问题:速度是个问题吗?我将假设您不是在c#这样的语言中执行此操作的,在c#语言中,异常很容易捕获。每个字符串更新一次。速度是个问题,但完成工作也很重要。
    1. Take a copy of the destination table:
    SELECT * INTO #Destination FROM DestinationTable WHERE 1=2
    GO
    2. Set ANSI_WARNINGS OFF and perform the insert into the copy of the destination table, then set ANSI_WARNINGS ON again:
    SET ANSI_WARNINGS OFF
    GO
    INSERT INTO #Destination
    SELECT * FROM SourceTable
    GO
    SET ANSI_WARNINGS ON
    GO
    As ANSI_WARNINGS is off SQL Server truncates the fields rather than produces the warning.
    3. Next compare what you would like to insert against what was inserted with the ANSI_WARNINGS OFF truncating. By using EXCEPT you only select the rows that don't match, and have therefore been truncated:
    SELECT * FROM SourceTable
    EXCEPT
    SELECT * FROM #Destination
    GO