根据this forum discussion,SQL Server(我使用的是2005,但我认为这也适用于2000和2008)会悄悄地将指定为存储过程参数的任何varchar
截断为varchar的长度,即使直接使用INSERT
插入该字符串实际上会导致错误.如果我创建这个表:
CREATE TABLE testTable(
[testStringField] [nvarchar](5) NOT NULL
)
然后当我执行以下命令时:
INSERT INTO testTable(testStringField) VALUES(N'string which is too long')
我得到一个错误:
String or binary data would be truncated.
The statement has been terminated.
太棒了数据完整性得到了保护,而且调用者知道这一点.现在,让我们定义一个存储过程来插入:
CREATE PROCEDURE spTestTableInsert
@testStringField [nvarchar](5)
AS
INSERT INTO testTable(testStringField) VALUES(@testStringField)
GO
并执行它:
EXEC spTestTableInsert @testStringField = N'string which is too long'
没有错误,1行受影响.表中插入一行,testStringField
作为"strin".SQL Server悄悄地截断了存储过程的varchar
参数.
现在,这种行为有时可能很方便,但我想没有办法关闭它.这是非常烦人的,因为如果我向存储过程传递太长的字符串,我会出错.似乎有两种方法可以解决这个问题.
首先,将存储的proc的@testStringField
参数声明为大小6,并判断其长度是否超过5.这看起来有点像黑客,涉及大量令人恼火的样板代码.
其次,只需将所有存储过程varchar参数声明为varchar(max)
,然后让存储过程中的INSERT
语句失败.
后者似乎工作得很好,所以我的问题是:如果我真的希望在传递的字符串太长时存储过程失败,那么在SQL Server存储过程中始终对字符串使用varchar(max)
是一个好主意吗?这可能是最佳实践吗?在我看来,无法禁用的silent截断似乎很愚蠢.