根据 这个论坛讨论,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
作为“ string”。SQLServer 悄悄地截断了存储过程的 varchar
参数。
现在,这种行为有时可能很方便,但我想没有办法把它关掉。这是非常恼人的,因为如果我向存储过程传递了太长的字符串,想要就会出错。有两种方法可以解决这个问题。
首先,将存储进程的 @testStringField
参数声明为大小6,并检查其长度是否超过5。这看起来有点像黑客行为,而且涉及到大量令人恼火的样板代码。
其次,只需将 ALL 存储过程 varchar 参数声明为 varchar(max)
,然后让存储过程中的 INSERT
语句失败。
后者似乎工作得很好,所以我的问题是: 如果我实际上希望存储过程在传递过长的字符串时失败,那么在 SQL Server 存储过程中对字符串使用 varchar(max)
ALWAYS 是一个好主意吗?这会是最好的练习吗?无法禁用的无声截断在我看来很愚蠢。