我同意@marc_s - 解决问题,而不是症状特别是如果您的意图是截断。当另一个开发人员出现并且 proc 抛出这些错误并且使用非标准标志来抑制问题时,他会怎么想?
使您的截断意图清晰的代码。
确定您的问题
小提琴不显示您描述的行为。所以我对这个问题仍然有些困惑。
此外,对于这样的问题,您的 SQL 小提琴太密集了。如果我没有在下面回答您的问题,请尽可能将问题隔离到最简单的用例中。不要只是将 500 行应用程序转储到一个窗口中。
注意:Max NVarchar 在 SQL 7 和 2000 版本中为 4000,在 SQL 2005 及更高版本中为 2 Gigs (nvarchar(max))。我不知道你从哪里想出 3072。
我的测试
如果您在 SPROC 参数 级别进行截断,ANSI 警告标志将被忽略,如 this MSDN page 警告。如果它在您的过程中,我创建了一个小测试过程,显示允许截断的 ANSI 标志:
CREATE Proc DoSomething (@longThing varchar(50)) AS
DECLARE @T1 TABLE ( shortThing VARCHAR(20) );
SET ANSI_WARNINGS OFF
Print ' I don''t even whimpler when truncating'
INSERT INTO @T1 (ShortThing) VALUES ( @longThing);
SET ANSI_WARNINGS ON
Print ' I yell when truncated'
INSERT INTO @T1 (ShortThing) VALUES ( @longThing);
然后调用它按预期工作:
exec DoSomething 'Text string longer than 20 characters'
解决问题
尽管如此,为什么不直接编写代码,以便(可能)截断数据的意图很明确?您可以避免警告而不是将其关闭。我会执行以下操作之一:
- 使您的过程参数足够长以容纳输入
- 如果您需要缩短字符串数据,请使用
Substring() 来修剪数据。
- 使用
CAST 或CONVERT 将数据格式化为您的要求。 This page(标题为“隐式转换”的部分应该有所帮助)详细说明了转换和转换的工作原理。
我上面的简单示例可以修改如下,以避免需要设置任何标志。
CREATE Proc DoSomethingBETTER (@longThing varchar(50)) AS
SET ANSI_WARNINGS ON
DECLARE @T1 TABLE ( shortThing VARCHAR(20) );
--try one of these 3 options...
INSERT INTO @T1 (ShortThing) VALUES ( Convert(varchar(20), @longThing));
INSERT INTO @T1 (ShortThing) VALUES ( Substring(@longThing, 1, 20));
INSERT INTO @T1 (ShortThing) VALUES ( Cast(@longThing as varchar(20)) );
Print('Ansi warnings can be on when truncating data');
旁白 - 集群向导
看着你的小提琴,我注意到你 Uniqueidentifer 是你聚集索引中的键。在几乎所有情况下,这都是一个非常低效的选择。 GUID 的随机性意味着您的数据不断被碎片化和重新洗牌。
希望您可以转换为int identity,您正在使用newsequentialid(),或Jimmy Nilsson's article 中所述的COMB guid。
您可以查看更多有关问题的信息here、here、here 和here。