2011-11-15 120 views
0

当更新一系列包含多个VarChar(n)列的表时,执行Replace操作的某些更新会使我的事务处理中“字符串或二进制数据将被截断”。我试图想出一个可重复的方法来处理这个问题。SQL Server字符串二进制数据将被截断捕获

一个选项是首先选择行ID和要变换的列的长度,如果其长度超过列的大小。我不是这样的粉丝,因为它看起来像我不会得到任何查询计划重用,它会执行得很慢。

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

我也可以通过获取新值的子字符串/左侧并放入它来忽略整个事情,但这会掩盖它并且不让我知道实际问题的位置。

我使用的是MSSQL 2008

编辑 - 这里的想法看起来有点前途: http://sqlblogcasts.com/blogs/danny/archive/2008/01/12/scuffling-with-string-or-binary-data-would-be-truncated.aspx

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 

回答

1

,您在更新源是什么?即你是否正在从另一个表中更新为基于集的操作,或者从一个应用程序的循环中更新行?

这只是一个特定的列的问题,或者你遇到的各种列?

问题越有针对性越容易修复。回答,然后我会更新我的答案和更多信息。基本上,虽然你想查询你的源数据只是不会导致问题和处理它们的记录。然后将其余的报告为异常和/或截断它们,以便它们可以被导入,如果这是你想要的。

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

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

+0

我正在从任意字符串更新。数据是要传送到下游系统的报告输出,有些数据需要追加,如追加文本末尾的“(已编辑)”。它有多个列,我已经坚持做动态SQL来首先创建更新语句。 – Snowy

+0

那么每个字符串都包含多个记录更新的数据,或者每个字符串只有一个记录更新?还有一个问题:速度是一个问题?我假设你不是用像c#这样的语言来做这件事,因为这些例外很容易被捕获。 –

+0

每个字符串更新一次。速度是一个问题,但完成工作也很重要。 – Snowy

1

“另一种办法是找出如何捕捉到行(第一 行?)导致失败,并报告给调用者。我不认为这 会工作,因为错误水平太高,让我找出 的问题。“

我认为你需要查明问题(即发生在哪一列)。如果不是这种情况,那么你可以做以下事情:

你可以尝试更新与ansi警告上,如果它导致错误,然后报告异常,关闭ansi警告并将其导入到表中,然后再次打开ansi警告。

但是,如果您确实需要查明问题,则需要更多代码才能找到问题...但出于速度考虑,您可能不希望主动寻找错误,因此您只能使用上述技术一旦sql告诉你有一个问题,请查找该问题。

相关问题